关于 JavaScript 浮点运算的精度解决方案

feikers 2019-06-26

问题背景

在 chrome 浏览器中调出开发者工具,在控制台窗口输入下面的表达式:

0.1 + 0.2            // 期望:0.3,结果:0.30000000000000004

这就是 JavaScript 臭名昭著的浮点值运算舍入误差问题。

原因

至于问题产生的原因,或者关于问题的更详细的描述,大家请看下面几个文章:

  • JavaScript浮点运算0.2+0.1 !== 0.3
  • javascript浮点值运算舍入误差
  • 【JS 基础】JS 浮点数四则运算精度丢失问题 (3)

解决方案

这里主要讨论一下解决方案的问题,上面几篇文章的解决思路,都是重写:加法、减法、乘法和除法运算。感觉过于啰嗦,方案不简洁。简单的办法就是,加、减、乘、除,该怎么算还怎么算。因为结果有问题,所以就在结果上做文章。解决问题的思路,其实就是考虑在计算结果上保留几位小数的问题。

代码如下:

/**
 * 小数点后面保留第 n 位
 *
 * @param x 做近似处理的数
 * @param n 小数点后第 n 位
 * @returns 近似处理后的数 
 */
function roundFractional(x, n) {
  return Math.round(x * Math.pow(10, n)) / Math.pow(10, n);
}

有了这个函数,那么加、减、乘、除的计算就变成下面的形式了:

roundFractional(0.1 + 0.2, 1);         // 结果:0.3
roundFractional(0.1 * 0.2, 2);         // 结果:0.02
                                       // 减法和除法依次类推,此处略掉两行

可以把下面的代码复制到 chrome 开发者工具的控制台中,观察一下运行效果:

function roundFractional(x, n) {
  return Math.round(x * Math.pow(10, n)) / Math.pow(10, n);
}
console.log(0.1 + 0.2);
console.log(roundFractional(0.1 + 0.2, 1));
console.log(0.1 * 0.2);
console.log(roundFractional(0.1 * 0.2, 2));

相关推荐