【JS 基础】JS 浮点数四则运算精度丢失问题 (3)
关于 JavaScript 浮点运算的精度解决方案
问题描述
1 |
|
产生原因
Javascript 采用了 IEEE-745 浮点数表示法(几乎所有的编程语言都采用),这是一种二进制表示法,可以精确地表示分数,比如 1/2,1/8,1/1024。遗憾的是,我们常用的分数(特别是在金融的计算方面)都是十进制分数 1/10,1/100 等。二进制浮点数表示法并不能精确的表示类似 0.1 这样 的简单的数字,上诉代码的中的 x 和 y 的值非常接近最终的正确值,这种计算结果可以胜任大多数的计算任务:这个问题也只有在比较两个值是否相等时才会出现。
javascript 的未来版本或许会支持十进制数字类型以避免这些舍入问题,在这之前,你更愿意使用大整数进行重要的金融计算,例如,要使用整数‘分’而不是使用小数‘元’进行货比单位的运算———以上整理自《Javascript 权威指南 P37》
0.1+0.2 的计算
首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)
双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。
解决方案 (引自:解决方案)
为了解决浮点数运算不准确的问题,在运算前我们把参加运算的数先升级(10 的 X 的次方)到整数,等运算完后再降级(0.1 的 X 的次方)。
1 |
|
此方案只支持浮点数,若想支持浮点数整数混用,请自行调整。
终极解决方案
解决问题的思路,其实就是考虑在计算结果上保留几位小数的问题。
1 |
|
roundFractional(0.1 + 0.2, 1); // 结果:0.3
其他解决方案
1 |
|
1 |
|