修正了javascript函数产生奇怪结果的问题?

kmynzznz  于 2023-02-02  发布在  Java
关注(0)|答案(5)|浏览(81)

我正在尝试将数字固定为小数点后2位数,为此我使用了javascript的toFixed函数。下面是我得到的奇怪结果,请检查并帮助我。

var number = 11.995;
number.toFixed(2); // **giving me 11.99 which is correct**

var number = 19.995;
number.toFixed(2); // **giving me 20.00 which is incorrect**

有谁能告诉我为什么会发生这种事。
谢谢你的帮助。

x3naxklr

x3naxklr1#

这就是浮点数学的工作原理。值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
b4lqfgs4

b4lqfgs42#

toFixed对值进行舍入。由于19.995正好是19.99和20.00的中间值,因此必须选择其中一个。传统上,舍入优先选择偶数结果(这可以防止偏差,因为上舍入和下舍入是相等的)。

svmlkihl

svmlkihl3#

我创造了一个能为我做一切的功能。

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);
ltqd579y

ltqd579y4#

我猜大卫已经回答了你的疑问。只是提供了一个替代的解决方案。
为此,可以使用Math对象的Math.floor()方法。
就像这样Math.floor(number*100)/100

scyqe7ek

scyqe7ek5#

有谁能告诉我为什么会发生这种事。
JavaScript的number类型使用的IEEE-754双精度二进制浮点数标准(在其他几种语言中也是如此)并不能完美地存储所有的数字,它 * 不精确地 * 存储了一些数字,其存储方式允许它A)仅以64位存储它们,B)快速地使用它们进行计算。
对于11.995,实际值为11.99**4**99988555908203125,仅比11.995稍微***小***。
对于19.995,实际值是19.9950008392333984375,只是比19.995稍微***多***。
这就解释了为什么当您使用通常的舍入到最接近的一半操作舍入它们时,11.995(实际上是11.99499988555908203125)向下舍入到11.99,而19.995(实际上是19.9950008392333984375)向上舍入到20.00

  • This site有一个方便的计算器,可以将这些东西可视化。)*

更多信息请访问SO:

相关问题