为什么0.1 +0.2===0.30000000000000004 ?
我们来推导一下0.1
0.1>>>二进制>>>科学记数法>>实际存储时的形式[64位] 符号位+(指数位+指数偏移量)+小数部分) 即:
0.1>>>0.0001100110011001100110011001100110011001100110011001101>>> 1.100110011001100110011001100110011001100110011001101 * 2^(-4)>>>
0011111110111001100110011001100110011001100110011001100110011010
同理,0.2
0.2>>二进制>>>科学记数法>>实际存储时的形式64位 即
0.2>>>0.001100110011001100110011001100110011001100110011001101>>>1.100110011001100110011001100110011001100110011001101 * 2^(-3)>>>0011111111001001100110011001100110011001100110011001100110011010
可以看出来在转换为二进制时
0.1 >>> 0.0001 1001 1001 1001...(1001无限循环)
0.2 >>> 0.0011 0011 0011 0011...(0011无限循环)
就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等,在转换为二进制的科学记数法的形式时只保留64位有效的数字,此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。在这一步出现了错误,那么一步错步步错,那么在计算机存储小数时也就理所应当的出现了误差。这即是计算机中部分浮点数运算时出现误差,这就是丢失精度的根本原因
将0.1和0.2的二进制形式按实际展开,末尾补零相加,结果如下
0.00011001100110011001100110011001100110011001100110011010
+0.00110011001100110011001100110011001100110011001100110100
=0.01001100110011001100110011001100110011001100110011001110
0.1+0.2 >> 0.0100 1100 1100 1100...(1100无限循环)
则0.1 + 0.2的结果的二进制数科学记数法表示为为1.001100110011001100110011001100110011001100110011010 * 2^(-2), 省略尾数最后的0,即 1.00110011001100110011001100110011001100110011001101 * 2^(-2), 因此(0.1+0.2)实际存储时的形式是 0011111111010011001100110011001100110011001100110011001100110100
因计算机存储位数的限制而截断的二进制数字,再转换为十进制,就成了0.30000000000000004
推导完成