5

我有可能是极端情况。当试图将值四舍五入4.015到小数点后 2 位时,我总是以4.01而不是预期的4.02. .015对于所有带有小数部分的数字,这种情况始终如一。

我在 JS 中使用了一个相当常见的方法:

val = Math.round(val * 100) / 100;

我认为问题是在乘以 100 时开始的。浮点不准确导致该值向下舍入而不是向上舍入。

var a = 4.015,                // 4.015
    mult = a * 100,           // 401.49999999999994 (the issue)
    round = Math.round(mult), // 401
    result = round / 100;     // 4.01 (expected 4.02)

小提琴:http: //jsfiddle.net/eVXRL/

如果我尝试四舍五入,则不会发生此问题4.025。的期望值4.03确实返回;.015这只是(到目前为止)的一个问题。

有没有办法优雅地解决这个问题?当然,.015一次性查找和处理该案例是有技巧的,但这似乎是错误的!

4

4 回答 4

4

我最终使用math.js进行数学运算,这解决了我所有的浮点问题。

这个库的优点是不需要实例化任何类型的 Big Decimal 对象(即使该库确实支持 BigDecimal)。它就像替换和传递精度一样Math简单math

于 2017-09-25T22:50:53.560 回答
2

浮点数不是实数,它们是浮点数。

有无数个实数,但只有有限的位数来表示它们,因此有时,如果您想要的确切数字无法在浮点系统中表示,则必须存在一些舍入误差。

因此,在处理浮点数时,您必须考虑到,您不会得到与您所想的完全相同的数字。
如果您需要一个确切的数字,您应该使用一个可以提供更好精度的库,通常它将使用一个定点和/或符号表示

更多信息可以在维基百科页面和这篇(有点复杂但重要的)文章中找到: 每个计算机科学家应该知道的关于浮点运算的知识

于 2013-08-09T08:49:33.827 回答
1

如果您要将数字用作小数,请使用十进制库,例如big.js

大多数语言(包括 javascript)中的浮点值都以二进制表示形式存储。大多数情况下,这符合您的预期。在这种情况下,您的 4.015 被转换为二进制字符串,并且恰好被编码为您看到的 4.014999999... 值,这是双精度(8 字节)IEEE754 值中可用的最接近的二进制表示。

如果您正在做金融数学,或人类消费的数学(即作为小数),那么您将希望 4.015 舍入到 4.02,并且您需要一个十进制库。

由于新的 IEEE754-2008 标准包括decimal32等作为十进制浮点值表示,因此计划在 javascript 中包含浮点值的十进制表示。在这里阅读更多:http: //speleotrove.com/decimal/

最后,如果您在 javascript 中进行会计数学(即不应该意外创造或消失金钱的财务计算),那么请以整美分/便士进行所有计算。

于 2013-08-15T15:40:36.040 回答
0

您可以使用正则表达式来提取和替换数字以获得您想要的:

val = (val + "").replace(/^([0-9]+\.[0-9])([0-9])([0-9]).*$/, function(whole, head, lastdigit, followup) {
    if(followup >= 5) {
        return head + ("" + (parseInt(lastdigit) + 1));
    }else return head + lastdigit;
});

否则,您可以使用val = val.toFixed(2)但特定值 4.015 给出 4.01(4.0151 给出 4.02 作为“预期”)。

于 2013-08-09T09:23:21.957 回答