2017-03-27 25 views
0

我知道我必须在这里丢失一些东西,我试图将任意数量的数字舍去到两位小数而没有成功。总计超过两个时,Javascript中舍入数字失败?

var sumOne = 0; 
var sumTwo = 0; 
[12.993, 12.99, 12.99].forEach(function(number){ 
    sumOne += roundOne(number * 0.1); 
    sumTwo += roundTwo(number * 0.1); 
}) 

function roundOne(n){ 
    return (Math.round((n *100))/100); 
} 
function roundTwo(n){ 
    return +(n.toFixed(2)); 
} 
console.log("sumOne is ", sumOne, " sumTwo is ", sumTwo); 

https://jsfiddle.net/m90ecdh9/1/

在此的jsfiddle或以上代码我结束了以下输出

sumOne is 3.9000000000000004 sumTwo is 3.9000000000000004 

为什么都四舍五入的这些方法不能导致总和只有两个小数?

奇怪的是,如果我在数组中只用两个数字来尝试这个相同的代码,我的结果与预期的结果一样,这两个方法只有两个小数位。

+0

你只是遇到了一些浮点舍入错误。这并不罕见。如果你绝对需要避免这些,强制你的变量使用整数类型。 – IvanSanchez

+0

* roundOne *函数有多余的括号:'return Math.round(n * 100)/ 100;'会做。这个名字似乎不合适,因为它四舍五入到小数点后两位。 – RobG

+0

另请参阅:[*为什么230/100 * 100不返回230?*](http://stackoverflow.com/questions/13248173/why-does-230-100100-not-return-230/13248284#13248284)和[*浮点数学是否被破坏?*](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – RobG

回答

0
var sumOne = 0; 
var sumTwo = 0; 
[12.993, 12.99, 12.99].forEach(function(number){ 

    sumTwo += roundTwo(number); // dont *0.1 
}) 

function roundOne(n){ 
    return (Math.round((n *100))/100); 
} 
function roundTwo(n){ 
    return +(n.toFixed(2)); 
} 
console.log("sumOne is ", sumOne, " sumTwo is ", sumTwo); 

https://jsfiddle.net/m90ecdh9/3/

我已删除了roundTwo(数×0.1),这使得正确sumTwo。

我不知道你为什么这样做。

这是现在四舍五入每个数字和总结。我认为这是所需的效果。

如果你想将它们四舍五入。然后在添加0.05之前添加到Fixed(2)。如果您想舍入减去0.05,则会将结果清除至小数点后两位。

1

它是浮点精度的问题。最简单的办法:

console.log("sumOne is ", sumOne.toFixed(2), " sumTwo is ", sumTwo.toFixed(2))

你也可以多你的号码1000,使他们成为整个数字,做他们的数学运算,然后通过1000又分为。

+0

使用乘法和除法来模仿* toFixed *不是一个好主意。使用1000的因子与100有相同的问题,请参阅[*为什么230/100 * 100不返回230?](http://stackoverflow.com/questions/13248173/why-does-230-100100-not -return-230)四舍五入应该留到最后,因为四舍五入误差累积,并且可能不一致,这取决于操作的顺序。 – RobG

+0

@RobG - 但是230 * 100/100没有返回230?答案建议在进行计算之前先乘以,然后再进行除法。 (虽然显然取决于计算,你仍然可以在中途得到小数位,我同意直到结束舍去。) – nnnnnn

+0

@ nnnnnn - 我猜如果输入始终是一个只有两位小数的字符串,并且没有任何算术产生分数,然后'* 100/100'工作,但它不是一个通用的解决方案。 – RobG