6

我这样做只是为了好玩(所以,不完全是一个问题,我可以看到降级已经发生了)但是,代替谷歌新发现的无法正确地数学 (检查它!根据谷歌 500,000,000,000,002 - 500,000,000,000,001 = 0),我想我会在 C 中尝试以下内容来运行一些理论。

int main()
{
   char* a = "399999999999999";
   char* b = "399999999999998";

   float da = atof(a);
   float db = atof(b);

   printf("%s - %s = %f\n", a, b, da-db);

   a = "500000000000002";
   b = "500000000000001";
   da = atof(a);
   db = atof(b);
   printf("%s - %s = %f\n", a, b, da-db);
}

当你运行这个程序时,你会得到以下

   399999999999999 - 399999999999998 = 0.000000
   500000000000002 - 500000000000001 = 0.000000

看起来 Google 使用的是简单的 32 位浮点精度(此处的错误),如果您在上面的代码中将浮点数切换为双精度,则可以解决问题!会是这样吗?

/mp

4

7 回答 7

4

有关更多这种愚蠢的信息,请参阅这篇关于 Windows 计算器的好文章。

当你改变内部时,没有人注意到

Calc 的内部结构——算术引擎——被完全抛弃并从头开始重写。标准 IEEE 浮点库被任意精度算术库所取代。这是在人们不断写下关于 Calc 如何无法正确进行十进制运算的哈哈文章之后完成的,例如计算 10.21 - 10.2 导致 0.0100000000000016。

于 2008-08-25T23:19:45.287 回答
2

看起来 Google 使用的是简单的 32 位浮点精度(此处的错误),如果您在上面的代码中将浮点数切换为双精度,则可以解决问题!会是这样吗?

不,你只是推迟这个问题。双打仍然表现出同样的问题,只是数字更大。

于 2008-08-26T08:08:31.007 回答
2

在 C# 中,尝试 (double.maxvalue == (double.maxvalue - 100)) ,你会得到真实的......

但这就是它应该是的:

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

考虑一下,您有 64 位表示大于 2^64(double.maxvalue)的数字,因此预计会不准确。

于 2008-08-26T08:19:56.813 回答
1

@ebel

考虑一下,您有 64 位表示大于 2^64(double.maxvalue)的数字,因此预计会不准确。

2^64 不是双精度数的最大值。2^64 是双精度(或任何其他 64 位类型)可以保存的唯一值的数量。 Double.MaxValue等于 1.79769313486232e308。

浮点数的不准确性并非来自表示大于的值Double.MaxValue(这是不可能的,不包括Double.PositiveInfinity)。它来自这样一个事实,即所需的值范围太大而无法适应数据类型。所以我们放弃精度来换取更大的有效范围。从本质上讲,我们正在减少有效数字以换取更大的指数范围。

@DrPizza

甚至不; IEEE 编码对相同的值使用多种编码。具体来说,NaN 由 all-bits-1 的指数表示,然后是尾数的任何非零值。因此,双打有 252 个 NaN,单打有 223 个 NaN。

真的。我没有考虑重复的编码。不过,实际上双打有 2 52 -1 NaN,单打有 2 23 -1 NaN。:p

于 2008-08-26T15:46:40.840 回答
0

2^64 不是双精度数的最大值。2^64 是双精度(或任何其他 64 位类型)可以保存的唯一值的数量。Double.MaxValue 等于 1.79769313486232e308。

甚至不; IEEE 编码对相同的值使用多种编码。具体来说,NaN 由 all-bits-1 的指数表示,然后是尾数的任何非零值。因此,双打有 2 52 个NaN,单打有 2 23个NaN。

于 2008-08-26T17:04:32.013 回答
0

真的。我没有考虑重复的编码。不过,实际上双打有 252-1 NaN,单打有 223-1 NaN。:p

哦,忘了减去无穷大。

于 2008-08-26T21:54:56.667 回答
0

我了解到的这个问题的粗略估计版本是 32 位浮点数为您提供 5 位精度,而 64 位浮点数为您提供 15 位精度。这当然会根据浮点数的编码方式而有所不同,但这是一个很好的起点。

于 2008-09-12T23:14:13.150 回答