原文地址:https://alphahinex.github.io/2022/03/20/javascript-rounding-off/
coverdescription: "通过最小的浮点数或科学记数法减少误差"
date: 2022.03.20 10:34
categories:
- JavaScript
tags: [JavaScript]
keywords: js, 四舍五入, toFixed, Number.EPSILON
由于 JS 中 Number 对象的 toFixed 方法在对某些值进行四舍五入计算时 存在误差,而这种误差在进行货币金额计算时是不能接受的,那么在 JS 中我们应该如何正确的进行四舍五入呢?
以保留两位小数为例,选取几种典型的方法,其中 n
为要进行四舍五入运算的浮点数。
方法 A
为 n 添加一个小的偏移量,再进行四舍五入:
(n + Number.EPSILON).toFixed(2)
方法 B
保留两位小数时,先将 n 扩大 10^2 倍,然后通过 Math.round
获得最接近的整数,缩小 10^2 倍后再进行四舍五入:
(Math.round(n * 100) / 100).toFixed(2)
方法 C
为 n 添加一个小的偏移量后,再进行方法 B 中的操作:
(Math.round((n + Number.EPSILON) * 100) / 100).toFixed(2)
方法 D
通过科学记数法进行方法 B 的操作:
(+(Math.round(n + "e2") + "e-2")).toFixed(2)
对比计算结果
n | 期望值 | 方法 A | 方法 B | 方法 C | 方法 D |
---|---|---|---|---|---|
0.995 | 1.00 | 1.00 (√) | 1.00 (√) | 1.00 (√) | 1.00 (√) |
2.005 | 2.01 | 2.00 (X) | 2.01 (√) | 2.01 (√) | 2.01 (√) |
5.475 | 5.48 | 5.47 (X) | 5.48 (√) | 5.48 (√) | 5.48 (√) |
1.005 | 1.01 | 1.01 (√) | 1.00 (X) | 1.01 (√) | 1.01 (√) |
0.014999999999999965 | 0.01 | 0.02 (X) | 0.01 (√) | 0.02 (X) | 0.01 (√) |
1.496e-7 | 0.00 | 0.00 (√) | 0.00 (√) | 0.00 (√) | NaN (X) |
可以看到,每种方法都有计算结果与预期不符的情况,但方法 C 仅在某些极端情况下会出现错误,方法 D 也仅在 n 只能使用科学计数法进行表示时才会出现 NaN 的情况。
结论
总体来说,方法 C 和 方法 D 的适用性更好,可以用来作为在 JS 中进行四舍五入运算的方式。
# n 为浮点数,代表要四舍五入的数
# m 为整数,代表小数部分保留的位数
# 方式一
(Math.round((n + Number.EPSILON) * Math.pow(10, m)) / Math.pow(10, m)).toFixed(m)
# 方式二
(+(Math.round(n + "e" + m) + "e-" + m)).toFixed(m)
网友评论