JavaScript 最多保留两位小数,别忘了浮点数边界

需求看起来很简单:1.7777 变成 1.789.1 仍然显示成 9.1,整数 10 也不要补成 10.00

toFixed() 后转回数字

toFixed(2) 会返回字符串,而且会补齐两位小数。前面加一个一元 +,可以把结果转回数字,多余的末尾零也会消失:

const value = 1.5;
const rounded = +value.toFixed(2);

console.log(rounded); // 1.5

如果目标是固定显示两位小数,例如价格必须显示为 1.50,就不要转回数字,直接保留 toFixed(2) 的字符串结果。这里讨论的是“最多两位”,所以才需要这一步转换。

Math.round() 也有边缘情况

常见写法是把小数放大 100 倍,四舍五入后再缩回去:

Math.round(num * 100) / 100

但 JavaScript 使用浮点数表示小数,某些输入并不能被精确保存。一个典型例子是:

Math.round(1.005 * 100) / 100 // 1,而不是 1.01

给原值加上 Number.EPSILON 可以修正一部分情况:

Math.round((num + Number.EPSILON) * 100) / 100

它并不是所有输入都适用。比如 1.3549999999999998 加上补偿后可能得到 1.36,而期望值可能是 1.35toFixed() 同样存在浮点数边界,旧版 Chrome 中 1.555.toFixed(2) 曾得到 "1.55"

所以这里没有一条适合所有业务的公式。普通展示可以选简洁写法;一旦舍入规则会影响金额或结算,就要先明确采用哪种舍入算法,再用对应的边界值做测试。