toFixed JavaScript函数给出奇怪的结果?

4

我正在尝试将数字保留两位小数,为此我使用了JavaScript的toFixed函数。以下是我得到的奇怪结果,请检查并帮助我。

var number = 11.995;
number.toFixed(2); // 得到正确的结果:11.99

var number = 19.995;
number.toFixed(2); // 得到错误的结果:20.00

请问有人能告诉我为什么会发生这种情况吗?

感谢您的帮助。

5个回答

6
这就是浮点数运算的原理。值19.995并不是精确的二进制数(基数为2)。为了更清楚地说明,想想当你将10除以3时得到的精确数字。

要获得更深入的解释,请阅读这个链接:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

在您的情况下,您可以使用字符串进行操作(至少似乎是您想要的):

number.toString().substr(0, n);

或者像这样定义一个函数(只是一个示例,仅用了2分钟):

Number.toFixed = function(no, n) {
    var spl = no.toString().split('.');
    if ( spl.length > 1 ) {
        return spl[0]+'.'+spl[1].substr(0,n);
    }
    return spl[0];
}

Number.toFixed(19.995, 2); // 19.99

@RobW 的确如此,但它并不是要完全替代,仅仅是理论上的。不过还是谢谢! - David Hellsing
在这种情况下,0,4只提供了1位小数。你最好使用indexOf来检测点,或者只需使用一个正则表达式:/-?\d+(\.\d{0,2})?/。注意:该正则表达式不完整,它不能处理指数。 - Rob W

2
我已经创建了一个函数,它为我完成了所有的工作...
    function toFixed(number, precision) {
        var multiplier = Math.pow(10, precision + 1),
            wholeNumber = Math.floor(number * multiplier);
        return Math.round(wholeNumber / 10) * 10 / multiplier;
    }

   //Call this function to retrive exect value
    toFixed((+adjustmentval), 2);

我的想法完全一样!太糟糕了,toFixed不会这样做 - 我们怎么知道可能会有问题呢?嗯,我想我们应该意识到这点... - iAmOren

1

toFixed将值四舍五入。由于19.995恰好处于19.99和20.00的中间,因此必须选择其中一个。传统上,四舍五入会优先选择偶数结果(这可以防止偏差,因为四舍五入的结果和舍去的结果将相等)。


它并不会“选择”。19.995 不是确切的中点,因为 JavaScript 中的浮点数并不是精确的。你可以通过将 19.999991 + 0.000004相加来测试这一点,结果为19.999995000000002 - David Hellsing
1
一些浮点数小数是精确的,例如0.5。不过,我之前关于它舍入至偶数的说法是错误的,它总是向上舍入。0.5.toFixed(0)等于1,1.5.toFixed(0)等于2。 - Barmar
2
不,它并不总是四舍五入,这就是最初的问题。例如(11.995).toFixed(2)是11.99。 - David Hellsing
1
那是因为你之前说的,它不是精确的。那些恰好在中间的会向上舍入。 - Barmar

0

我猜David已经回答了你的疑问。这里提供另一种解决方案。

你可以使用Math对象的Math.floor()方法来实现。

像这样:Math.floor(number*100)/100


0
有人能告诉我为什么会发生这种情况吗?
JavaScript的number类型(以及其他几种语言中的类似类型)使用的IEEE-754双精度二进制浮点数标准并不能完美地存储所有数字,它以一种让它A)只用64位存储它们,B)快速计算它们的方式存储一些数字不精确
对于11.995,实际值是11.99499988555908203125,略小于11.995。
对于19.995,实际值是19.9950008392333984375,略大于19.995。

这就解释了为什么使用通常的四舍五入操作时,11.995(实际上是11.99499988555908203125)向下舍入到11.99,但19.995(实际上是19.9950008392333984375)向上舍入到20.00

此网站有一个方便的计算器来可视化这些内容。)

在SO上还有更多信息:


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