toFixed(2)无法一致地对"x.525"进行四舍五入?

7

在使用 toFixed 时,我遇到了舍入误差的问题。

我在数值计算中使用了 toFixed(2),但对于一些情况,舍入结果并非如预期所示。

假设将toFixed(2)应用于值17.525,则结果为17.52。而如果将其应用于5.525,则结果为5.53

在后一种情况下,四舍五入结果是准确的,那么请问如何获得像后一种情况中的准确舍入结果?或者,您能否提供替代 toFixed 函数以获得正确的舍入结果的建议?


1
FYI,这与jQuery无关。它是一个JavaScript函数。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed。 - alexn
2
那个结果完全没问题。尾数-指数浮点数是一个谎言。试试 toFixed(20) 然后比较一下。 - user166390
可能是重复的问题:使用 toFixed(2) 和 Math.round 来获得正确的四舍五入 - user166390
我相信如果你执行 17.525.toFixed(2),你会得到 17.53(我是这样的),所以 17.52 的结果是由另一个小于 17.525 的值产生的。 - panda-34
我认为这只是在某些浏览器中不一致(IE11似乎是一致的,FF和Chrome不一致)。请参见此答案以获取适用于所有浏览器的函数。 - Hanna
显示剩余4条评论
4个回答

5

浮点数不准确意味着大多数以 .525 结尾的数字实际上是 .52500..1,而其他数字则是 .5249999.....

值向哪个方向舍入取决于IEEE-754浮点数中最接近所需值的实际表示是在所需值的上方还是下方。


17.525.toFixed(3) "17.525" 保留三位小数得到 "17.525",但是去掉最后一位得到 "17.52" 是错误的吗?不过我在不同的浏览器中得到了不同的结果,所以我怀疑 toFixed 不太可靠 :P - Esailija
@Esailija 不,我认为在那种情况下17.52是一个有效的响应。 - Alnitak
@Alnitak,也许我误解了OP,因为他说那是错的...但另一方面,他接受了这个答案,所以我也不知道 :) - Esailija
@Esailija 是的,我刚意识到它对于17.529也做了错误的事情。嗯。 - Alnitak
@Alnitak,不同的浏览器也有差异,对我来说17.525.toFixed(2)在Chrome中是"17.52",但在IE9中是"17.53"。因此,最可能需要一些自定义解决方案。 - Esailija

2

不要使用toFixed(),而应该使用Math.ceil()Math.floor()Math.round()

可以采用类似如下方式

var rnum = 5.525,
    decimalPlaces = 2,
    factor = Math.pow(10, decimalPlaces),
    newnumber = Math.round(rnum * factor) / factor,
    mydecimalvalue = parseFloat(newnumber); 

结果为 5.53


但是这些返回整数值...它怎么能在这里使用呢? - user166390
将数字乘以100后,数字已经失去了精度,因此使用这些方法并没有真正帮助。 - nhahtdh
@rab nawaz khan:你得到的结果是5.23,但应该是5.53,这怎么可能呢?这与预期结果相差甚远。 - Akshay

1

将数字转换为字符串并进行操作?

这是在我尝试使用Math.round或模拟最近舍入的Math.ceil失败后的最后手段。当乘以100时,一些数字(如17.525)会比其值的100倍(1752.5)略小,而其他数字(如17.545)则会比其值的100倍(1754.5)略大。


我并不确定将数字转换为字符串如何有所帮助... 这似乎只是更多的工作。 - user166390
我们将使用十进制表示法而不是二进制表示法来处理这个数字。当我们在舍入之前和之后打印数值时,它会“视觉上正确”。 - nhahtdh

1
使用 Intl.NumberFormat,并在选项中设置minimumFractionDigitsmaximumFractionDigits为相同的数字(您想要显示的位数)。

const formatter = [0, 1, 2, 3, 4, 5].map(
    (decimals) =>
        new Intl.NumberFormat('en-US', {
            minimumFractionDigits: decimals,
            maximumFractionDigits: decimals,
        }),
);

console.log(formatter[2].format(17.525)); // 17.53
console.log(formatter[2].format(5.525)); // 5.53
console.log(formatter[2].format(1.005)); // 1.01
console.log(formatter[2].format(8.635)); // 8.64
console.log(formatter[2].format(8.575)); // 8.58
console.log(formatter[2].format(35.855)); // 35.86
console.log(formatter[2].format(859.385)); // 589.39
console.log(formatter[2].format(859.3844)); // 589.38
console.log(formatter[2].format(.004)); // 0.00
console.log(formatter[2].format(0.0000001)); // 0.00

// keep in mind that this will not be formatted as expected, as the value that
// you pass is actually 0.07499999999998863. 
console.log(formatter[2].format(239.575 - 239.5)); // 0.07
console.log(formatter[2].format(0.07499999999998863)); // 0.07


使用此格式化程序尝试值41.354675返回结果为41.35: - JabbyPanda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接