谷歌计算器故障,浮动与双精度可能是一个可能的原因吗?
由于 Google 新发现无法执行数学 正确 (检查一下!根据 Google 500,000,000,000,002 - 500,000,000,000,001 = 0< /code>),我想我应该在 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位浮点精度(这里的错误),如果你在上面的代码中将float切换为double,你就可以解决问题! 会是这样吗?
With Google's newfound inability to do math correctly (check it! according to Google 500,000,000,000,002 - 500,000,000,000,001 = 0
), I figured I'd try the following in C to run a little theory.
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);
}
When you run this program, you get the following
399999999999999 - 399999999999998 = 0.000000
500000000000002 - 500000000000001 = 0.000000
It would seem like Google is using simple 32 bit floating precision (the error here), if you switch float for double in the above code, you fix the issue! Could this be it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我了解到的这个问题的粗略估计版本是,32 位浮点数为您提供 5 位精度,64 位浮点数为您提供 15 位精度。 当然,这会根据浮点数的编码方式而有所不同,但这是一个非常好的起点。
The rough estimate version of this issue that I learned is that 32-bit floats give you 5 digits of precision and 64-bit floats give you 15 digits of precision. This will of course vary depending on how the floats are encoded, but it's a pretty good starting point.
哦,忘记减去无穷大了。
Doh, forgot to subtract the infinities.
有关更多此类愚蠢内容,请参阅这篇有关 Windows 计算器的好文章。
当你改变内部结构时,没有人会注意到
For more of this kind of silliness see this nice article pertaining to Windows calculator.
When you change the insides, nobody notices
甚至不; IEEE 编码对相同值使用多种编码。 具体来说,NaN 由全位 1 的指数表示,然后尾数为任何非零值。 因此,双打有 252 NaN,单打有 223 NaN。
Not even; the IEEE encodings use multiple encodings for the same values. Specifically, NaN is represented by an exponent of all-bits-1, and then any non-zero value for the mantissa. As such, there are 252 NaNs for doubles, 223 NaNs for singles.
@玉宝
2^64 不是 double 的最大值。 2^64 是 double(或任何其他 64 位类型)可以保存的唯一值的数量。
Double.MaxValue
等于 1.79769313486232e308。浮点数的不准确性并非来自于表示大于
Double.MaxValue
的值(这是不可能的,不包括Double.PositiveInfinity
)。 这是因为所需的值范围太大,无法适应数据类型。 所以我们放弃精度来换取更大的有效范围。 从本质上讲,我们正在删除有效数字以换取更大的指数范围。@DrPizza
真的。 我没有考虑重复的编码。 不过,实际上双打有 252-1 NaN,单打有 223-1 NaN。 :p
@ebel
2^64 is not the maximum value of a double. 2^64 is the number of unique values that a double (or any other 64-bit type) can hold.
Double.MaxValue
is equal to 1.79769313486232e308.Inaccuracy with floating point numbers doesn't come from representing values larger than
Double.MaxValue
(which is impossible, excludingDouble.PositiveInfinity
). It comes from the fact that the desired range of values is simply too large to fit into the datatype. So we give up precision in exchange for a larger effective range. In essense, we are dropping significant digits in return for a larger exponent range.@DrPizza
True. I didn't account for duplicate encodings. There are actually 252-1 NaNs for doubles and 223-1 NaNs for singles, though. :p
不,你只是推迟这个问题。 双打仍然表现出同样的问题,只是数量更大。
No, you just defer the issue. doubles still exhibit the same issue, just with larger numbers.
在 C# 中,尝试
(double.maxvalue == (double.maxvalue - 100))
,您将得到true
但 这就是它应该的样子。想想看,您有 64 位表示大于
2^64
(double.maxvalue
) 的数字,因此不准确是意料之中的。In C#, try
(double.maxvalue == (double.maxvalue - 100))
, you'll gettrue
but that's what it is supposed to be.Thinking about it, you have 64 bit representing a number greater than
2^64
(double.maxvalue
), so inaccuracy is expected.