文字来源: www.ctoku.com/post/eVXV0B…
我们都知道0.1+0.2 = 0.3
但是在js中
0.1+0.2 = 0.30000000000000004
1.1*100 = 110.00000000000001
1-0.9 = 0.09999999999999998
复制代码
那么为什么会造成这样的误差呢?
首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:
0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)
复制代码
由于0.1和0.2转换成二进制是成为一个无限循环的数字,但是计算机是不允许无限循环的,对于无限循环的小数,计算机会进行入舍处理,进行双精度浮点数的小数部分最多支持 52位。
由于存储位数限制因此存在“舍去”,精度丢失就发生了。
解决方案
我们找到了出现误差的原因之后,那么解决就有了思路。
知道要保留的小数位数
(0.1+0.2).toFixed(1) = 0.3
这个toFixed()就可以解决这个问题,但是对于一些极为严格的金额计算这种办法就会出现问题,不推荐使用。
JavaScript数学库 Math.js
math.js是JavaScript和Node.js广泛的数学库。它具有一个灵活的表达式解析器和提供了一个集成的解决方案。
它强大和易于使用。
三种安装方式
通过npm安装:
npm install mathjs
通过bower安装:
bower install mathjs
math.js 可以从cdnjs 下载或者链接:
https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.16.0/math.min.js
使用方式
用静态函数和常数(就像JavaScript的Math对象)
math.round(math.e, 3); // 2.718
math.add(2, 3); // 5
math.sqrt(-4); // 2i
math.pow([[-1, 2], [3, 1]],2); // [[7, 0], [0, 7]]
math.derivative('x^2 + x', 'x'); // 2 * x + 1
math.atan2(3, -3) / math.pi; // 0.75
复制代码
对字符串表达式进行求值运算
math.eval('12 / (2.3 + 0.7)'); // 4
math.eval('12.7 cm to inch'); // 5 inch
math.eval('sin(45 deg) ^ 2'); // 0.5
math.eval('9 / 3 + 2i'); // 3 + 2i
math.eval('det([-1, 2; 3, 1])'); // -7
复制代码