Javascript 精度2019-10-22Θ
Javascript 中的数字按照 IEEE754 标准,使用 64 位双精度(double)浮点型来表示(统一处理整数和小数,节省存储空间)。ES5规范:
S
1位符号位(Sign),为 +1 或 -1;E
11位指数位(Exponent), 范围 [-1074, 971], 包括两端值;M
52位尾数位(Mantissa),正整数并且小于 2^53。
数值表示#
大数精度#
总结#
[MIN_SAFE_INTEGER, MAX_SAFE_INTEGER] 范围的整数可以精确展示,超出则会有精度问题。
精度问题#
问题分析#
十进制浮点数转二进制方法
- 比如十进制 0.125,先乘 2, 得 0.25, 取整数部分 0;
- 将小数部分 0.25 乘 2,等 0.5, 取得整数部分 0;
- 将小数部分 0.5 乘 2,得到整数部分 1;
- 得到二进制 0.001
浮点数二进制转十进制方法
- 0.001,第一位为 0,十进制为 0 * 1 / 2;
- 第二位为 0,十进制为 0 * 1 / 4;
- 第二位为 1,十进制为 1 * 1 / 8;
- 汇总得到十进制为: 0 * 1 / 2 + 0 * 1 / 4 + 1 * 1 / 8 = 0.125
解决思路#
- 浮点数运算偏差很小,可以直接进行
四舍五入
,比如parseFloat((0.1 + 0.2).toFixed(12)) === 0.3
; - 浮点数转成整数运算,再做除法。比如
(0.1 * 10 + 0.2 * 10)/10 === 0.3
; - 把浮点转成字符串,模拟实际运算。
- 第一种方案,在一些极端情况下还是会有问题;
- 第二种方案,number-precision 就是使用这种方案,也有问题:
- 第三种方案有很多成熟的库,比如 bignumber.js,decimal.js, big.js。这些库修复了浮点精度、toFixed 问题,并且支持大数据计算。