浮点数在计算机底层的表示及运算
1.浮点数在计算机底层存储机制
单精度浮点数float占4字节32位,双精度浮点数double占8字节64位。float和double的二进制存储结构都是:符号位+指数位+尾数位
- 符号位:表示浮点数的正负,0:正 1:负
- 指数位:控制浮点数数值的大小
- 尾数位:控制浮点数的精度
float32的位数
符号位 | 指数位 | 尾数位 |
---|---|---|
1 | 8 | 23 |
float64的位数
符号位 | 指数位 | 尾数位 |
---|---|---|
1 | 11 | 52 |
比如我们要把float32的6.125转化为 二进制的表示
- 符号位 正数为0,负数为1,所以6.125的符号位为 1
- 指数位 首先把6.125转成二进制的小数.
- 整数部分 5 转二进制等于 110
- 小数部分乘以2取整,然后正序排列
0.125 * 2 0
0.25 * 2 0
0.5 * 2 1
小数部分等于101, 结果为110.001 科学计数法表示 1.10001 * 2^2,所以指数为2,由于指数也分正负 2^8 范围是-127 ~ 128 正数需要 + 127 指数位等于127+2 = 129 转化为二进制为 10000001
尾数位 1.10001 小数点前面的是隐藏位不需要 后面补齐 所以尾数位为 10001000000000000000000
最终6.125的二进制表示为 01000000110001000000000000000000
2.浮点数的计算机底层加法运算过程
我们都知道float64 中 0.1 + 0.2 != 0.3 那么就来看一下浮点数计算的过程
- 首先把0.1和0.2 分别转换成二进制表示为
0.1 0(符号位) 01111111011(指数位) 1001100110011001100110011001100110011001100110011010(尾数位)
0.2 0(符号位) 01111111100(指数位) 1001100110011001100110011001100110011001100110011010(尾数位)
- 指数位对阶:一般是用小的指数减去大的 01111111011 - 01111111100 = -1 所以0.1 的尾数位右移一位 (tips:浮点数尾数位隐藏位默认是1)
0.1 尾数位 1.1001100110011001100110011001100110011001100110011010 右移一位
得到 0.1100110011001100110011001100110011001100110011001101(0)
按照0舍1进, 0舍去,所以得到
0.1100110011001100110011001100110011001100110011001101
0.1 和0.2 的尾数相加得到
1.1001100110011001100110011001100110011001100110011010
0.1100110011001100110011001100110011001100110011001101
10.0110011001100110011001100110011001100110011001100111
- 正规化 根据正规化要求,我们把结果右移一位,并且指数位+1
1.0011001100110011001100110011001100110011001100110011(1)
进1
1.0011001100110011001100110011001100110011001100110100
- 最后得到的二进制为
0 01111111101 0011001100110011001100110011001100110011001100110100
转化十进制
0.30000000000000004
所以现在知道为什么 0.1 + 0.2 != 0.3 了吧
本作品采用《CC 协议》,转载必须注明作者和本文链接