float 和 double 的表示法:
都是二进制的科学表示法:
± mantissa × 2 exponent
(mantissa:尾数,exponent:指数,均使用二进制表示)
float(浮点型)在内存中占4个字节(Byte),即32位(bit)
存储方式如下:
1 bit(符号位) | 8 bit(指数位) | 23 bit(尾数位) |
符号位:1 bit,0表正,1表负
指数为:8 bit,推算的8个bit能表示的范围为0 - 2的8次方减1,即0 - 255,但是这里的值都是加了127的,所以实际能表示的范围为:-127 - 128
尾数位:23 bit,推算得23个bit能表示的范围为0 - 2的23次方减1,即0 - 8388607,最大值为7位数,但是不能表示所有的7位数,不过所有的6位数是可以包含的,所以精度为6个有效数字(注:这也就是为什么说float的精度为6-7位,但实际能确定的只有6位)
所以我们比较两个float是否相等时,常常这样写:
最大值:由上面得指数最大为128,即此时最大值为2的128次方,为 3.402823466E+38
最小值:符号位为1时,表负,所以最小值即最大值取负的即可,为 -3.402823466E+38
当指数为-127时,决定了浮点数所能表达的绝对值最小的非零数,为1.175494351E-38
double(双精度浮点型)在内存中占8个字节(Byte),即64位(bit)
存储方式如下:
1 bit(符号位) | 11 bit(指数位) | 52 bit(尾数位) |
符号位:1 bit,0表正,1表负
指数为:11 bit,推算的11个bit能表示的范围为0 - 2的11次方减1,即0 - 2047,但是这里的值都是加了1023的,所以实际能表示的范围为:-1023 - 1024
尾数位:52 bit,推算得52个bit能表示的范围为0 - 2的52次方减1,即0 - 4503599627370495,最大值为16位数,但是不能表示所有的16位以内的数,但是所有的15位数是可以包含的,所有精度为15个有效数字
最大值:由上面得指数最大为1024,即此时最大值为2的1024次方,为 1.7976931348623158E+308
最小值:符号位为1时,表负,所以最小值即最大值取负的即可,为 - 1.7976931348623158E+308
当指数为-1023时,决定了浮点数所能表达的绝对值最小的非零数,为2.2250738585072014E-308
举个例子:
1. 得到float类型的 -10.5 的内存表示
首先得到-10.5的二进制表示法,- 1010.1,二进制的科学表示法为:- 1.0101 * 2的3次方
这样可以得到
符号位:因为是负的,所以为1
指数位:上面得到指数为3,加上127得到130,二进制表示为10000010
尾数位:只表示小数点后面的即可,即0101,后面补0即可,一共23位,需补19个0,最终二进制表示为:0101 0000 0000 0000 0000 000
最后把上面的符号位,指数位,尾数位加起来就得到了二进制表示:(红色表符号位,绿色表指数为,蓝色表尾数位)
110000010 01010000000000000000000
按照8个bit一个byte,区分开来得到
1100 0001 0010 1000 0000 0000 0000 0000 十六进制表示即为:0x c1 28 00 00
由于机器为小端,低位先存,高位后存,所以内存中实际存储为:
0000 0000 0000 00000010 10001100 0001十六进制表示即为:0x 00 00 28 c1
可以写个程序测试下,你会发现-10.5的内存表示确实是0x 00 00 28 c1
2. 一个小端机器中,float的内存数据为 0x 00 00 85 41,求这个float数
首先,由于是小端,得到原本的十六进制:0x 41 85 00 00
得到二进制数据:0100 0001 1000 0101 0000 0000 0000 0000
再以颜色区分(红色表符号位,绿色表指数为,蓝色表尾数位)
得到数据: 0100 0001 1000 0101 0000 0000 0000 0000
然后提取得到:
符号位:0,表正数
指数位:10000011,即十进制数131,减去127后得到4
尾数位:000 0101 0000 0000 0000 0000 舍去后面多余的0,即0000101
由上面公式得到,该float数据为 1.0000101 * 2的4次方,小数点右移4位,即10000.101
小数点左边数据,10000即16
小数点右边数据,0.101即1*2^-1 +0 * 2^-2 +1* 2^-3
最后左右加后边,即16+0.625 = 16.625
可以写个程序测试下,你会发现16.625的内存表示确实是0x 00 00 85 41