HOWTO · JavaScript
在 JavaScript 中将数字四舍五入到小数点后两位
本教程讲解如何在 JavaScript 中将数字四舍五入至最多 2 位小数?
本页内容
需要固定显示小数点后两位时,使用 toFixed(2)。它会返回字符串,因此末尾的零会保留下来。若需要数值结果,可使用 Math.round(value * 100) / 100,或用 Number() 将格式化后的字符串转换为数字。这些方法适用于一般数值,但 JavaScript 使用二进制浮点数存储数字,因此像 1.005 这样的十进制输入,舍入结果可能与预期不同。
使用 toFixed() 格式化数字
对数字调用 toFixed(2),会得到一个包含两位小数的字符串。当你要显示标签、表格单元格或其他内容,并且希望 5.60 保留末尾的零时,这种方法很有用。不过,返回值是文本;若要用它进行算术运算,必须先将其转换回数字。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
const value = 5.6789;
const fixedText = value.toFixed(2);
const roundedValue = Math.round(value * 100) / 100;
const numericValue = Number(value.toFixed(2));
function roundToTwo(number) {
const shifted = Number(`${number}e2`);
return Number(`${Math.round(shifted)}e-2`);
}
const shiftedValue = roundToTwo(value);
console.log(fixedText, roundedValue, numericValue, shiftedValue);
5.68 5.68 5.68 5.68
按顺序,这些值分别是 toFixed() 返回的字符串、Math.round() 得到的数字、经 Number() 转换后的数字,以及十进制移位辅助函数的结果。只有第一个值是文本;用 Number() 转换后会得到数字,也不会保留末尾的零。
使用 Math.round() 舍入数字
乘以 100 会将百分位移到个位。Math.round() 会把缩放后的值舍入为整数,再除以 100 即可恢复原来的小数位数。结果仍是数字,便于后续计算,但不会记录应显示多少位小数。
Math.round() 会将正好位于中间的值舍入到正无穷方向。例如,-1.5 这样的中间值会舍入为 -1,因此负数并不遵循总是远离零舍入的规则。此外,乘法本身也使用浮点运算;这种写法虽然简洁,但不能保证所有输入都能得到精确的十进制舍入结果。
了解浮点数的边界情况
JavaScript 的 Number 类型使用二进制浮点数表示数值。许多十进制小数无法用二进制精确表示,中间运算结果也可能略低于或高于人们预期的十进制值。常见例子是 1.005:它的存储值略小于对应的十进制小数,因此 1.005.toFixed(2) 可能得到 "1.00";先缩放再调用 Math.round() 也可能产生意外结果。
Number.EPSILON 表示 1 与下一个可表示数字之间的间隔。在舍入前加上它,有时能帮助处理接近 1 的输入,但可表示数字之间的间隔会随数值大小而改变。因此,固定的 epsilon 修正无法解决所有数值或所有运算过程造成的问题。
toPrecision() 控制的是有效数字位数,而不是小数点后的位数。例如,Number((1.23456).toPrecision(4)).toFixed(2) 会得到 "1.24",而 (1.23456).toFixed(2) 会得到 "1.23":前一种写法先将数值舍入到 1.235,然后再次舍入这个中间值。这是一个特定的双重舍入案例,并不是通用修正方法;第一次格式化可能会丢弃后续步骤所需的信息。
使用十进制移位辅助函数
上面的辅助函数通过指数表示法移动十进制位,舍入移位后的数值,再将小数位移回原处。与直接将十进制小数乘以 100 相比,这种写法可以避开某些意外结果,同时仍返回数字。若要舍入到其他小数位数,请相应调整指数:向前移位时使用该位数,移回时使用其相反数。
应将这个辅助函数视为处理一般有限数值的一种实用方法,而不是十进制运算库。浮点数表示的限制仍然存在,极大数值或特殊值也可能需要单独处理。如果金额或会计计算要求精确的十进制行为,可在适用时使用整数表示最小货币单位,或选择一款符合应用规则的十进制运算库。格式化显示结果与执行精确的十进制计算是两种不同的需求。
选择合适的方法
如果需要固定宽度的显示文本,选择 toFixed(2);它会保留末尾的零,并返回字符串。如果需要简洁的数值结果,且输入范围适合一般浮点运算,可选择 Math.round(value * 100) / 100。如果希望先采用 toFixed() 的舍入行为,再得到数字,可选择 Number(value.toFixed(2));但要记住,数字不会保留显示格式。了解其限制后,也可以考虑使用十进制移位辅助函数作为另一种数值处理方法。
这些方法都无法让 JavaScript 数字变成精确的十进制数。对于界面显示,应在实际显示时进行格式化。对于有严格十进制规则的计算,应明确规定舍入策略和数字表示方式,再使用应用领域中的代表性数值进行测试。