JavaScript 浮点数精度丢失原理与修复方案
JavaScript 中 0.1 + 0.2 不等于 0.3 是由于 IEEE 754 二进制存储导致的精度丢失。本文解析十进制转二进制的原理,并介绍使用 Decimal、Bignumber 库及整数放大法修复该问题的具体方案。
前言
在 JavaScript 中进行十进制数值运算时,常会遭遇出乎意料的计算结果,这是开发者普遍遇到的现象。
精度丢失
以 0.1 加 0.1 为例,结果为正常的 0.2;但计算 0.1 加 0.2 时,结果并非预期的 0.3,而是 0.30000000000000004。
此类现象不仅限于加法,减法运算中同样存在。
例如执行 1.2 减 1,结果返回 0.19999999999999996。
这并非 JavaScript 独有缺陷,其他编程语言同样面临此问题。
在 Python 环境下进行相同测试。
print(.1 + .2) 输出结果同样显示为:0.30000000000000004
原因
根本原因在于计算机底层以二进制格式存储数据。
如何将整数从十进制转换为二进制
十进制整数可通过连续除以 2 转换为二进制。记录每次除法的商,持续操作直至商为零。
每次除法需记录余数,最后将余数列表反转,即可得到对应的二进制数值。
以将 29 转换为二进制为例:
29÷2=14余1
14÷2=7余0
7÷2=3余1
3÷2=1余1
1÷2=0余1
由此得出,十进制 29 对应的二进制数为 11101。
其他示例:
1 对应二进制 1
10 对应二进制 1010
将小数从十进制转换为二进制
十进制小数转二进制采用“乘2取整,顺序排列”法。具体步骤为:用 2 乘以十进制小数,取积的整数部分;再用 2 乘以剩余的小数部分,再次取整数部分,如此循环,直至小数部分为零(此时 0 或 1 为最后一位),或达到所需精度。
例如将 0.375 转换为二进制:
0.375*2=0.75 得到整数部分 0
0.75*2=1.5 得到整数部分 1
0.5*2=1 得到整数部分 1,小数部分归零,计算结束。最终二进制表示为 0.011
其他示例:
- 0.1 的二进制表示为 0.0001100110011001100110011001100110011001100110011001101
- 0.2 的二进制表示为 0.001100110011001100110011001100110011001100110011001101
并非所有十进制数都能用二进制完美表示,部分数字转换后会产生无限循环小数。
JavaScript 计算时会先将十进制数转换为二进制进行运算。
0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111上述二进制结果 0.0100110011001100110011001100110011001100110011001100111 转换回十进制后即为 0.30000000000000004。
解决方案
第三方库
Decimal
x = new Decimal(0.1)
y = x.plus(0.2) bignumber
x = new BigNumber(0.1)
y = x.plus(0.2) 变成整数
核心思路是:将小数拆分为字符串,计算小数部分的长度,利用该长度将小数放大为整数进行计算。
function add(num1, num2) {
const num1Len = (num1.toString().split('.')[1] ).length;
const num2Len = (num2.toString().split('.')[1] ).length;
const maxLen = Math.pow(10, Math.max(num1Len, num2Len));
return (num1 * maxLen + num2 * maxLen) / maxLen;
}总结
至此,关于JavaScript中数字精度丢失问题的成因剖析与应对策略的探讨告一段落。如需获取更多有关JS数字精度丢失的相关信息,敬请查阅本站过往文章或继续阅读下文。期待大家持续支持本站!
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
