在开发中经常遇到过小数计算不精确的问题,比如0.1+0.2!==0.3 、0.1 + 0.7 !==0.8等,下面我们来追本溯源,看看为什么会出现这种现象,以及该如何避免。
精度丢失
计算机中所有的数据都是以二进制存储的,所以在计算时计算机要把数据先转换成二进制进行计算,然后在把计算结果转换成十进制。
但在计算0.1+0.2时,二进制计算发生了精度丢失,导致再转换成十进制后和预计的结果不符。
对结果的分析—更多的问题
0.1和0.2的二进制都是以1100无限循环的小数,下面逐个来看JS帮我们计算所得的结果:
0.1的二进制:
0.0001100110011001100110011001100110011001100110011001101
0.2的二进制:
0.001100110011001100110011001100110011001100110011001101
理论上讲,由上面的结果相加应该:
0.0100110011001100110011001100110011001100110011001100111
实际JS计算得到的0.1+0.2的二进制(JS采数字采用IEEE 754 双精度 64 位浮点数来存储,只能保存小数点52位,53位为0省略,53位为1进1,所以0.1+0.2二进制理论相加结果第53位为1所以进1得到实际二进制计算结果):
0.0100110011001100110011001100110011001100110011001101 // 换算为十进制为0.30000000000000004
同理:0.2+0.3 == 0.5
0.2转二进制:0.0100110011001100110011001100110011001100110011001101
0.3转二进制:0.001100110011001100110011001100110011001100110011001101
理论两者相加二进制:0.100000000000000000000000000000000000000000000000000001
实际相加只取小数点后52位:0.1000000000000000000000000000000000000000000000000000 // 0.5