Number.EPSILON
借助该属性解决浮点数计算产生的精度问题
Number.EPSILON
是 JavaScript 中表示最小精度的常量(约为 2.220446049250313e-16
),它可以用来比较两个浮点数是否“足够接近”。虽然 Number.EPSILON
本身不能直接用于浮点数运算,但可以借助它来实现更精确的比较和运算。
以下是借助 Number.EPSILON
实现浮点数运算并消除精度问题的几种方法:
1. 精确比较浮点数
使用 Number.EPSILON
比较两个浮点数是否相等:
function isEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true
2. 浮点数运算的封装
封装一个工具函数,确保浮点数运算的结果在精度范围内正确:
function addFloats(a, b) {
const sum = a + b;
// 如果结果与预期值的误差小于 Number.EPSILON,则返回预期值
if (Math.abs(sum - (a + b)) < Number.EPSILON) {
return a + b;
}
return sum;
}
console.log(addFloats(0.1, 0.2)); // 0.30000000000000004
3. 浮点数运算的修正
在运算后对结果进行修正,确保其精度在可接受范围内:
function preciseAdd(a, b) {
const sum = a + b;
// 如果结果与预期值的误差小于 Number.EPSILON,则返回修正后的值
if (Math.abs(sum - (a + b)) < Number.EPSILON) {
return Math.round((a + b) * 1e12) / 1e12; // 修正精度
}
return sum;
}
console.log(preciseAdd(0.1, 0.2)); // 0.3
4. 通用浮点数运算工具
封装一个通用的浮点数运算工具,支持加、减、乘、除:
function preciseOperation(operation, a, b) {
const result = operation(a, b);
// 如果结果与预期值的误差小于 Number.EPSILON,则返回修正后的值
if (Math.abs(result - operation(a, b)) < Number.EPSILON) {
return Math.round(result * 1e12) / 1e12; // 修正精度
}
return result;
}
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
const divide = (a, b) => a / b;
console.log(preciseOperation(add, 0.1, 0.2)); // 0.3
console.log(preciseOperation(subtract, 0.3, 0.1)); // 0.2
console.log(preciseOperation(multiply, 0.1, 0.2)); // 0.02
console.log(preciseOperation(divide, 0.3, 0.1)); // 3
5. 结合 toFixed()
和 Number.EPSILON
toFixed()
和 Number.EPSILON
在运算后使用 toFixed()
控制小数位数,并结合 Number.EPSILON
进行修正:
function preciseAdd(a, b) {
const sum = a + b;
const fixedSum = Number(sum.toFixed(10)); // 控制小数位数
// 如果结果与预期值的误差小于 Number.EPSILON,则返回修正后的值
if (Math.abs(fixedSum - sum) < Number.EPSILON) {
return fixedSum;
}
return sum;
}
console.log(preciseAdd(0.1, 0.2)); // 0.3
总结
精确比较:使用
Number.EPSILON
比较浮点数是否相等。运算修正:在运算后对结果进行修正,确保其精度在可接受范围内。
通用工具:封装通用的浮点数运算工具,支持加、减、乘、除。
结合
toFixed()
:使用toFixed()
控制小数位数,并结合Number.EPSILON
进行修正。
通过这些方法,可以更优雅地解决 JavaScript 浮点数运算中的精度问题。
最后更新于
这有帮助吗?