Math.round()和.toFixed()中的四舍五入问题

8

我使用了以下两种方法:

Number.prototype.myRound = function (decimalPlaces) {
    var multiplier = Math.pow(10, decimalPlaces);

    return (Math.round(this * multiplier) / multiplier);
};
alert((239.525).myRound(2));

数学上应该是 239.53,但输出结果是 239.52

所以我尝试使用 .toFixed() 函数,并得到了正确的答案。

但是当我尝试获取 239.575 的答案时,它再次给出了错误的输出。

alert((239.575).toFixed(2));

这里输出应该是239.58,但实际上显示的是239.57。这个错误会导致最终输出结果有一点差别。有人能帮我解决这个问题吗?

1
有趣的是,在Chrome 31(Mac)中,239.375.toFixed(2)返回"239.38"... :) - VisioN
1
可能是broken toFixed implementation的重复问题。 - VisioN
@VisioN 不在这里。你使用的是哪个浏览器?我在Ubuntu上使用的是最新版的FF。 - Cedric Reichenbach
@CedricReichenbach Chrome 31 在 MacOS 上。 - VisioN
更简单的解决方案: 截断小数函数 - David
更简单的解决方案: 截断小数位函数 - David
8个回答

12

这个方法将会给出非常准确的四舍五入结果。

function RoundNum(num, length) { 
    var number = Math.round(num * Math.pow(10, length)) / Math.pow(10, length);
    return number;
}

只需要调用这个方法。

alert(RoundNum(192.168,2));

它运行良好。它适用于所有条件。 非常感谢你。 - Surendra
1
正如TJ Crowder在https://dev59.com/xGkw5IYBdhLWcg3wQ4Zc中提到的,尝试使用RoundNum(35.855, 2)。 更好的答案可能是在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round中的十进制舍入示例。 - theycallmethesloth
10
RoundNum(1.005,2)被四舍五入为1,但期望结果是1.01。 - A Kunin

7

在内部,239.575无法准确表示。在二进制中,0.575会像1/2 + 1/16 + 1/128 + 1/256 + ...这样。

恰巧,在二进制中表示的结果略小于239.575。因此,Math.round向下舍入。

为了演示,请尝试以下操作:

alert(239.575 - 239.5)

您期望的结果应该是0.075,但实际上得到的是0.07499999999998863。

虽然这是真的,我从来没有在其他语言中看到过这样的“问题”... 这绝对是JavaScript必须改进的地方。 - VisioN
@VisioN 对于使用双精度浮点数的任何语言都是正确的。几乎所有语言都使用双精度浮点数,除了那些具有定点或任意精度系统的语言。 - Niet the Dark Absol

3

只需使用 Math.round

function round(figureToRound){
    var roundOff = Math.round((figureToRound* 100 ).toFixed(2))/100;
    return roundOff;
}

console.log(round(1.005));

这将完全解决四舍五入问题。


对我来说适用于所有情况。 round(239.575 - 239.5) 0.08 round(239.575) 239.58 round(239.525) 239.53 round(1.005) 1.01 - googamanga
无法处理round(0.07499)。它返回0.08,而不是0.07。 - dugokontov

2

round()函数可以实现这个功能。试试这个:

var v= Math.round(239.575 * 100) / 100;
alert(v);

Working FIddle


2
问题可能是浮点数精度不准确,因此在不同情况下(数字的收集方式不同、不同的浏览器等)可能会得到不同的结果。
另请参见:toFixed(2) rounds "x.525" inconsistently?

0
在我的软件中,我使用了以下代码:

(require DecimalJS)

Number.prototype.toFixed = function(fixed) {
    return (new Decimal(Number(this))).toFixed(parseFloat(fixed) || 
0);
};


var x = 1.005;
console.log( x.toFixed(2) ); //1.01

0

我得到了这个来简单地覆盖它 ->

Number.prototype.toFixed = function(fractionDigits, returnAsString = true) {
    var digits = parseInt(fractionDigits) || 0;
    var num = Number(this);
    if( isNaN(num) ) {
        return 'NaN';
    }
    
    var sign = num < 0 ? -1 : 1;
    if (sign < 0) { num = -num; }
    digits = Math.pow(10, digits);
    num *= digits;
    //num = Math.round(num.toFixed(12));
    num = Math.round( Math.round(num * Math.pow(10,12)) / Math.pow(10,12) );
    var ret = sign * num / digits;
    return (returnAsString ? ret.toString() : ret ); // tofixed returns as string always
}

0
function bestRound(val, decimals){
    decimals = decimals || 2;
    var multiplier = Math.pow(10, decimals)
    return Math.round((val * multiplier ).toFixed(decimals)) / multiplier;
  }

bestRound(239.575 - 239.5)   0.08
bestRound(239.575)         239.58
bestRound(239.525)         239.53
bestRound(1.005)             1.01

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