javaScript 中的精度丢失问题主要源于 IEEE 754 浮点数表示标准。这是现代计算机普遍使用的浮点数表示方法,它规定了如何在二进制中存储和处理小数。
浮点数表示的基础知识
- IEEE 754 标准:
- JavaScript 的
Number类型是基于 IEEE 754 的 64 位双精度浮点数 - 一个浮点数用 64 位存储
- 二进制存储的局限性:
- 并非所有的小数都能用二进制精确表示。例如:十进制的
0.1在二进制中是一个 无限循环小数,计算机只能截断并近似存储 - 类似地,
0.2也会被近似存储
- 运算中的累积误差:
- 当执行
加减乘除时,近似值的误差可能被放大,从而导致结果不精确。
工作中常用解决方法
- 转换为整数计算(用的不多,仅用于了解)
- 通过将浮点数转换为整数进行计算,避免精度丢失,最后再转换回浮点数。
function add(a, b) {
const factor = Math.pow(10, Math.max(decimalPlaces(a), decimalPlaces(b)));
return (a * factor + b * factor) / factor;
}
function decimalPlaces(num) {
const str = num.toString();
return str.includes('.') ? str.split('.')[1].length : 0;
}
console.log(add(0.1, 0.2)); // 0.3
- 使用
toFixed方法(适用于简单运算且小数位固定)
- 使用
toFixed将结果格式化为固定小数位数的字符串,并根据需要转换为数字。 - 注意:
toFixed会进行四舍五入。
- 使用第三方库
decimal.js(适用于高精度需求或复杂运算)