如何正确处理 Javascript 浮点表示错误?[复制]

How to properly deal with Javascript float representation errors? [duplicate]

提问人:hosstay 提问时间:4/16/2021 最后编辑:General Grievancehosstay 更新时间:4/16/2021 访问量:92

问:

例如:

sum = 0.00;

sum += 46.85 * 0.1;
console.log(sum) // 4.6850000000000005

sum += 179.29 * 0.1;
console.log(sum) // 22.613999999999997

我相信我也通过简单的加法和简单的乘法来实现了这一点。

我知道这是无法在计算机中正确握住浮子的结果,这很好。但是,据我所知,Postgres 似乎可以很好地处理这些操作。Javascript 似乎没有,这似乎很奇怪,除非我遗漏了什么。

无论如何,我目前的解决方法是像这样运行它:

const fixFloatError = (n) => {
  decimalDigitLength = n.match(/\.(\d+)/)[1].length;
  return parseFloat(parseFloat(n).toFixed(decimalDigitLength - 1));
}

let n = String(46.85 * 0.1);
n = fixFloatError(n);

如果您想知道我为什么要事先将其转换为字符串,那是因为 Javascript 会在进入函数时自动将像 22.6139999999999997 这样的浮点数转换为 22.614(这是正确修复的!无论您是将该数字硬编码到变量中还是通过乘法生成它),以及诸如 4.685000000000000005 到 4.685000000000000005(没有改变)之类的东西。因此,为了获得适用于这两种情况的一致函数,我将浮点数作为字符串传入以保持其形式。

当然,我在这里遗漏了一些东西,并且有更简单的解决方案吗?

JavaScript 浮点精度

评论

0赞 PM 77-1 4/16/2021
这很简单 - 如果你需要精度,那么不要使用浮点数。如果没有,就拿走你得到的。
0赞 hosstay 4/16/2021
@YonatanVainer - 感谢您的链接。该线程中公认的答案确实很好地解释了事情。我确实在与货币打交道,这就是为什么我需要准确的东西。正如我所想的那样,我要么需要在每次操作后运行一个函数,要么使用自定义数据类型。谢谢你的资源。
0赞 Bergi 4/16/2021
"据我所知,Postgres 似乎可以很好地处理这些操作。- 它可能没有使用双打

答:

0赞 Scott Marcus 4/16/2021 #1

只需将浮点数乘以 10 的某个系数即可创建更大的整数部分。然后将余数四舍五入并除以相同的系数。

let sum = 46.85 * 0.1;
console.log(sum) // 4.6850000000000005

sum = (Math.round(sum * 1000000000)) /  1000000000;

console.log(sum); // 4.685

评论

0赞 hosstay 4/16/2021
这似乎确实解决了我的函数的字符串要求。你的基本上做同样的事情,不需要我把它作为一个字符串传进来。不过,我仍然必须在每次操作后调用它,我关心使用结果。这是意料之中的,而无需像其他人建议的那样执行自定义数据类型。谢谢。