Open
Description
前言
正文
JavaScript是如何表示数字的?
JavaScript使用Number类型表示数字(整数和浮点数),遵循 IEEE 754 标准 通过64位来表示一个数字
- 第0位:符号位,0表示正数,1表示负数(s)
- 第1位到第11位:储存指数部分(e)
- 第12位到第63位:储存小数部分(即有效数字)f
既然说到这里,再给大家科普一个小知识点:js最大安全数是 Number.MAX_SAFE_INTEGER == Math.pow(2,53) - 1, 而不是Math.pow(2,52) - 1, why?尾数部分不是只有52位吗?
这是因为根据浮点数的存储原理,整数位第一位肯定是1,所以这个第一位就可以省略掉。因此多出了1位。(假设第一位是0的话,可以通过移动指数位调整。)
只有 JavaScript 中存在吗?
这显然不是的,这在大多数语言中基本上都会存在此问题(大都是基于 IEEE 754 标准)
JavaScript
console.log(.1 + .2); // 0.30000000000000004
Python
print(repr(.1 + .2)) # 0.30000000000000004
Java
System.out.println(.1 + .2); // 0.30000000000000004
System.out.println(.1F + .2F); // 0.3
怎么解决精度问题?
1、将数字转成整数
function add(num1, num2) {
const num1Digits = (num1.toString().split('.')[1] || '').length;
const num2Digits = (num2.toString().split('.')[1] || '').length;
const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
return (num1 * baseNum + num2 * baseNum) / baseNum;
}
但是这种方法对大数支持的依然不好
2、三方库
这个是比较全面的做法,推荐2个我平时接触到的库
- Math.js
专门为 JavaScript 和 Node.js 提供的一个广泛的数学库。支持数字,大数字(超出安全数的数字),复数,分数,单位和矩阵。 功能强大,易于使用。
官网:mathjs.org/ - big.js
官网:mikemcl.github.io/big.js
不过很多时候,一个函数能解决的问题不需要引用一个类库来解决。