提问人:mauriciopastrana 提问时间:8/26/2008 最后编辑:Stephen Ostermillermauriciopastrana 更新时间:9/8/2023 访问量:2578
谷歌计算器故障,浮动与双倍可能是一个原因吗?
The Google Calculator Glitch, could float vs. double be a possible reason?
问:
由于谷歌新发现的无法正确地进行数学运算(根据谷歌的说法),我想我应该尝试用 C 语言运行以下方法来运行一点理论。500,000,000,000,002 - 500,000,000,000,001 = 0
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 位浮点精度(此处出现错误),如果您在上面的代码中将浮点数切换为 double,则可以解决问题!难道是这样吗?
答:
有关更多此类愚蠢行为,请参阅这篇与 Windows 计算器有关的好文章。
Calc 的内部结构 - 算术 引擎 - 完全被扔掉了 并从头开始重写。这 标准IEEE浮点库 替换为 任意精度算术 图书馆。这是在人们之后完成的 不停地写哈哈的文章 Calc 无法进行十进制算术 正确地,例如计算 10.21 - 10.2 的结果为 0.01000000000000016。
似乎 Google 正在使用简单的 32 位浮点精度(此处出现错误),如果您在上面的代码中将浮点数切换为 double,则可以解决问题!难道是这样吗?
不,你只是推迟问题。双打仍然表现出同样的问题,只是数字更大。
在 C# 中,尝试 ,你会得到,但这就是它应该的样子。(double.maxvalue == (double.maxvalue - 100))
true
考虑一下,您有 64 位表示大于 () 的数字,因此预计会不准确。2^64
double.maxvalue
@ebel
考虑一下,您有 64 位表示大于 2^64 (double.maxvalue) 的数字,因此预计会不准确。
2^64 不是双精度的最大值。2^64 是双精度值(或任何其他 64 位类型)可以容纳的唯一值数。 等于 1.79769313486232e308。Double.MaxValue
浮点数的不准确性不是来自表示大于的值(这是不可能的,不包括)。它来自这样一个事实,即所需的值范围太大而无法适应数据类型。因此,我们放弃了精度,以换取更大的有效范围。从某种意义上说,我们正在删除有效数字以换取更大的指数范围。Double.MaxValue
Double.PositiveInfinity
@DrPizza
甚至没有;IEEE 编码对相同的值使用多个编码。具体来说,NaN 由全位 1 的指数表示,然后是尾数的任何非零值。因此,双打有 252 个 NaN,单打有 223 个 NaN。
真。我没有考虑重复的编码。不过,双打实际上有 2 个52-1 NaN,单打有 2个 23-1 NaN。:p
2^64 不是双精度的最大值。2^64 是双精度值(或任何其他 64 位类型)可以容纳的唯一值数。Double.MaxValue 等于 1.79769313486232e308。
甚至没有;IEEE 编码对相同的值使用多个编码。具体来说,NaN 由全位 1 的指数表示,然后是尾数的任何非零值。因此,双打有 252 个 NaN,单打有 223 个 NaN。
真。我没有考虑重复的编码。不过,双打实际上有 252-1 NaN,单打有 223-1 NaN。:p
哎呀,忘了减去无穷大。
我了解到的此问题的粗略估计版本是 32 位浮点数为您提供 5 位精度,而 64 位浮点数为您提供 15 位精度。当然,这将根据浮点数的编码方式而有所不同,但这是一个很好的起点。
评论