78

可能的重复:
JavaScript 的数学被破坏了吗?

为什么 JS 搞砸了这个简单的数学?

console.log(.1 + .2)  // 0.3000000000000004
console.log(.3 + .6)  // 0.8999999999999999

第一个示例大于正确结果,而第二个示例小于正确结果。???你如何解决这个问题?在执行操作之前,您是否必须始终将小数转换为整数?我是否只需要担心添加(* 和 / 在我的测试中似乎没有同样的问题)?

我在很多地方寻找答案。一些教程(如购物车表单)假装问题不存在,只是将值相加。大师们为各种数学函数提供了复杂的例程,或者顺便提到 JS “做得不好”,但我还没有看到解释。

4

5 回答 5

44

这不是 JS 问题,而是更通用的计算机问题。浮点数无法正确存储所有十进制数,因为它们以二进制形式存储内容例如:

0.5 is store as b0.1 
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc

so in binary 0.1 is 0.00011... 

但这是无止境的。除了计算机必须在某个时候停止。因此,如果在我们的示例中我们停在 0.00011,我们将得到 0.09375 而不是 0.1。

无论如何,重点是,这不取决于语言,而是取决于计算机。取决于语言的是你如何显示数字。通常,该语言将数字四舍五入为可接受的表示形式。显然 JS 没有。

所以你要做的(内存中的数字足够准确)只是告诉JS在将它们转换为文本时以“很好”的数字舍入。

您可以尝试使用该sprintf功能可以很好地控制如何显示数字。

于 2010-08-09T10:38:23.533 回答
22

来自浮点指南

为什么我的数字,比如 0.1 + 0.2 加起来不是很好的 0.3 轮,而是得到一个奇怪的结果,比如 0.30000000000000004?

因为在内部,计算机使用的格式(二进制浮点)根本无法准确表示 0.1、0.2 或 0.3 之类的数字。

当代码被编译或解释时,你的“0.1”已经被四舍五入到该格式中最接近的数字,这会在计算发生之前导致一个小的舍入误差。

该站点提供了详细的解释以及有关如何解决问题(以及如何确定在您的情况下是否存在问题)的信息。

于 2010-08-09T10:31:13.390 回答
8

这不仅仅是 javascript 的限制,它适用于所有浮点计算。问题是 0.1 和 0.2 和 0.3 不能完全表示为 javascript(或 C 或 Java 等)浮点数。因此,您看到的输出是由于这种不准确造成的。

特别是只有某些 2 的幂的和是可精确表示的。0.5 = =0.1b = 2^(-1), 0.25=0.01b=(2^-2), 0.75=0.11b = (2^-1 + 2^-2) 都可以。但是 1/10 = 0.000110001100011..b 只能表示为 2 的无限次方之和,语言在某些时候会切断它。正是这种斩波导致了这些轻微的错误。

于 2010-08-09T10:28:50.320 回答
5

这对于所有编程语言都是正常的,因为并非所有十进制值都可以精确地用二进制表示。看看每个计算机科学家应该知道的关于浮点运算的知识

于 2010-08-09T10:23:47.600 回答
1

它与计算机如何处理浮点数有关。您可以在此处阅读更多信息:http: //docs.sun.com/source/806-3568/ncg_goldberg.html

于 2010-08-09T10:22:32.187 回答