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是否相等时,常常这样写:

const float EPSILON = 0.000001;

float f1 = 123.234567;
float f2 = 123.234568;

if (fabs(f1-f2) <= EPSILON)
{
cout<<"equal"<<endl;
}
else
{
cout<<"not equal"<<endl;
}


最大值:由上面得指数最大为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