数据结构浅
数据结构
整型
1. 原码、反码、补码
对于整型来说,内存中存放的是补码
1.1 正数
正数的原码、反码、补码都是相同的。
//32位下
int a=1;
//原码:00000000 00000000 00000000 00000001
//反码:00000000 00000000 00000000 00000001
//补码:00000000 00000000 00000000 00000001
1.2 负数
二级制第一位(符号位)为1的是负数。
- 负数原码:二级制码
- 负数反码:符号位不变,其他位按位取反
- 负数补码:反码+1
int a=-1;
//原码:10000000 00000000 00000000 00000001
//反码:11111111 11111111 11111111 11111110
//补码:11111111 11111111 11111111 11111111
为什么要用补码存储呢?
因为cpu只能对数据进行加法操作(减法操作:a+(-b)),如果用原码进行存储,就会出现如下情况:
//用原码操作
1 + (-1) = -2 //肯定不对
//00000000 00000000 00000000 00000001
//10000000 00000000 00000000 00000001
//10000000 00000000 00000000 00000010
当用原码存储的时候,数据的减法操作会出错(加法操作正常),那么怎么保证数据的加减操作数据一致呢?
有人想到了补码这个玩意!
//用补码操作
1 + (-1) = -2 //肯定不对
//00000000 00000000 00000000 00000001
//11111111 11111111 11111111 11111111
//1 00000000 00000000 00000000 00000000此时会多一位,但只有32位,多的就去掉了
//00000000 00000000 00000000 00000000结果就是0了
使用补码进行存储整型数据,保证了数据的加减一致。
2. 字节存储模式
2.1 大端存储模式:
数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中。
//0x 11 22 33 44
//低地址------>高地址
|1|1|2|2|3|3|4|4|
2.2 小端存储模式:
数据的低位保存在内存的低地址中,而数据的地位保存在内存的高地址中。
//0x 11 22 33 44
//低地址------>高地址
|4|4|3|3|2|2|1|1|
3. 浮点型
3.1 存入
IEEE754-1985提供了四种精度规范, 其中最常用的是 单精度浮点型 和 双精度浮点型 , 但IEEE754并没有规定32位浮点数类型需要叫做 float, 或64位浮点数需要叫做 double.
它只是提供了一些关于如何存储不同精度浮点数的规范和标准. 不过一般情况下, 如果我们提到 float, 其实指的就是IEEE754标准中的32位单精度浮点数. 如果我们提到 double, 其实指的就是IEEE754标准中的64位双精度浮点数。
任意一个浮点数v在内存中都是以二进制形式存储的,如下:
(-1)^S * M * 2^E
S:符号位,正数则为0,负数则为1
M:表示有效数字,大于等于1,小于2
2^E:表示指数位(因为是二进制,所以为2的指数)
3.1.1 对于32位浮点数
其内存分配为:1位符号位,8位指数位,23位有效数字位
[][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]
S1 |E指数位 8 | 有效数字 23位
3.1.2 对于64位浮点数
其内存分配为:1位符号位,11位指数位,52位有效数字位
而IEEE754对有效数字M和指数E有特殊规定:
- 因为有效数字M的范围为:1<= M < 2,也就是说,M的形式永远都是1.xxxxxx,那么1就可以在内存中省去,这样对于内存中的有效数字位就可以多一位表示。比如1.01,在保存时,有效数字位只保存01,在取该浮点数时,再把1加上,即1.01即可。如32位浮点数,留给有效数字只有23位,那么采用该规则后,有效数字其实就为24位。高位去1,低位补0
- 而指数位时无符号型int,但是指数有正有负,那么负数怎么办呢?32位浮点数指数位的范围为0-255,取中间值127,在存指数位时加上127,然后存入。如:十进制指数位为-1,那么存入的值就为-1+127=126的二进制数;十进制指数位为2,那么存入的值就为2+127=129的二进制数。64位浮点数指数位的范围为0-2047,那么取中间值1023。
32位
十进制2.5 转换为二进制10.1=1.01 * 2^1
(-1)^S * M * 2^E
(-1)^1 * 1 * 2^1
//内存中:
1 10000000 01000000000000000000000
浮点数的存入为:符号位(正0负1,占1位)指数位(加127/1023,占8/11位)有效数字位(去整数位1,只存小数位,占23/52位)
3.2 取出
3.2.1 指数位不全为0或1
按存入方式反转之后取出。
3.2.2 指数位全为0
若指数位全为0:00000000 十进制表示为E+127=0,E= -127,该32位浮点数为:1.xxx*2^-127,该数无限接近于0。
此时,规定指数为(1-127)= -126/(1-1023)= -1022,有效数字位不加上去掉的1,即0.xxx,这样的方式是为了表示无限接近于0的正负小数。
3.2.3 指数位全为1
若指数位全为1:11111111 十进制表示为E+127=255,E=128,该32位浮点数为:
1.xxx*2^128,该数无限大。
此时,如果有效位数全为0,则表示正负无穷大。