JS中的舍入:不一致和意外的行为

问题描述:

我正在处理相对较小且简单的数字。我第一次试图做出四舍五入(数字后2个符号)与臭名昭着的toFixed。这是一个已知的问题:有时它不正确。但让我印象深刻的是,它也可以不一致JS中的舍入:不一致和意外的行为

(0.395).toFixed(2); // "0.40" 
(0.295).toFixed(2); // "0.29" 

这些数字都非常相似,数字后3个迹象,但不同的行为。

所以,我决定切换到使用Math.round。不久,我遇到了另一个问题:

Math.round(0.35055 * 10000)/100; // produces 35.05 instead of 35.06 

Math.round也有问题吗?那么,应该使用什么方法?

+0

FWIW最后一个问题发生在Math.round之前:'0.35055 * 10000' - >'3505.4999999999995' –

+0

为什么'0.35055 * 1000'等于'3505.4999999999995'而不是'3505.5'? – Manav

+0

检查这些答案:[这里](https://*.com/q/5490687/1823841),[这里](https://*.com/q/10768083/1823841) –

不幸的是,JavaScript已知存在如下精确问题,这些问题在以下问题中得到了更好的解释:Is floating point math broken?,正如评论中指出的那样。

如果您需要更高程度的数值准确性,我建议您使用库,如BigNumber,它也有自己的toFixed方法。

你的例子是这个样子:

var a = new BigNumber('0.35055'); 
a = a.times(10000) 
a = a.dividedBy(100) 
console.log(a.toFixed(2)); //would log "35.06" 

为了简便起见,你也可以连锁经营,像这样:a.times(10000).dividedBy(100).toFixed(2)

+1

我通过以下解决方法解决了我的问题: 'Math.round((0.35055 * 100)* 100)/ 100;' 但显然,您的解决方案更好,谢谢。 – Zaziro

我想这是事先设计好的。请记住,这些数字存储在基数2中,因此在转换为基数10时会损失精度。如果您想了解这些转换为什么看起来不一致,则必须查看这些转换。如果您想精确保留固定的小数位数,则可以使用整数进行操作并仅转换用于显示。