文章目录
引入
问题:
输入并运行以下代码:
#include<stdio.h>
#include<math.h>
int main(int argc, char* argv[])
{
int nValue = 1;
int nValue1 = 8388608;//2^23
int nValue2 = 16777216;//2^24
int nValue3 = 16777217;//2^24+1
printf("%f\r\n", (float) nValue );
printf("%f\r\n", (float) nValue1);
printf("%f\r\n", (float) nValue2);
printf("%f\r\n", (float) nValue3);
return 0;
}
会出现以下结果:
我们使用强制转化
发现第三行和第四行的数值是相等的,并不是我们所期望的结果,其本质原因就是整型转浮点型的方法导致
整型如何转化为浮点型
浮点数的存储机制为 (-1)^s * M * 2^E
当整数转换为浮点数时,首先位序列小数点移至最高位1的后面,如
15
=
1111
=
1.111
∗
2
3
15 = 1111 = 1.111 * 2^3
15=1111=1.111∗23
由此可知 s = 0, M = 1.111 = 1 + 1/2 + 1/4 + 1/8, E = 3.
换算后 可得15.0f 的二进制序列为
0 1000 0010 111 0000 0000 0000 0000 0000.
问题就在移动小数点,如果该整数的值大于2^24,即最高位1后面有24位甚至更多位,浮点数的有效位只会保存最高位1后面23位值,其余的都被rounding了。从而导致可能的精度丢失,比如
int a = pow(2,24)+1;
位序列为 0000 0001 0000 0000 0000 0000 0000 0001
移动小数点 =》 1.000 0000 0000 0000 0000 0000 × 2^24
最低位的1就被rounding了。
所以归根到底,当被rounding的位有1时,精度就变化了。
同时,double 为 1个符号位 , 11 个指数位, 52 个有效位,故 int 到double 不会丢失精度。