C语言 谷歌计算器故障,可以浮动与,这是一个可能的原因吗?

t5fffqht  于 12个月前  发布在  其他
关注(0)|答案(7)|浏览(122)

用Google新发现的inability来做mathcorrectly(检查一下!根据Google 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位浮点精度(这里的错误),如果你在上面的代码中将float切换为double,你就解决了这个问题!难道就是这个?

33qvvth1

33qvvth11#

对于更多的这种愚蠢的看到这个不错的文章有关Windows计算器。
When you change the insides, nobody notices
Calc的内部--算术引擎--被完全抛弃,从头开始重写。标准IEEE浮点库被替换为任意精度算术库。这是在人们不断写哈哈文章关于Calc如何无法正确进行十进制算术之后完成的,例如计算10.21 - 10.2导致0.01000000000016。

xwmevbvl

xwmevbvl2#

在C#中,尝试(double.maxvalue == (double.maxvalue - 100)),你会得到true,但这就是它应该是什么。
考虑一下,你有64位代表一个大于2^64double.maxvalue)的数字,所以不准确是意料之中的。

e0bqpujr

e0bqpujr3#

看起来Google使用的是简单的32位浮点精度(这里的错误),如果你在上面的代码中将float切换为double,你就解决了这个问题!难道就是这个?
不,你只是推迟了这个问题。双打仍然表现出同样的问题,只是数字更大。

cczfrluj

cczfrluj4#

@ebel
仔细想想,你有64位表示一个大于2^64(double.maxvalue)的数,所以不准确是意料之中的。
2^64不是double的最大值。2^64是double(或任何其他64位类型)可以保存的唯一值的数量。Double.MaxValue等于1.79769313486232e308。
浮点数的不准确性并不来自表示大于Double.MaxValue的值(这是不可能的,不包括Double.PositiveInfinity)。它来自于这样一个事实,即所需的值范围太大,无法适应数据类型。所以我们给予精度来换取更大的有效范围。在本质上,我们正在丢弃有效数字,以换取更大的指数范围。
@DrPizza
不是偶数; IEEE编码对相同的值使用多种编码。具体地,NaN由所有位1的指数表示,然后是尾数的任何非零值。因此,双打有252个NaN,单打有223个NaN。
是的。我没考虑到重复编码。实际上,双打有252-1 NaN,单打有223-1 NaN。:p

4sup72z8

4sup72z85#

2^64不是double的最大值。2^64是double(或任何其他64位类型)可以保存的唯一值的数量。Double。MaxValue等于1.79769313486232e308。
不是偶数; IEEE编码对相同的值使用多种编码。具体地,NaN由所有位1的指数表示,然后尾数为 any 非零值。因此,双打有252个NaN,单打有223个NaN。

8ftvxx2r

8ftvxx2r6#

是的。我没考虑到重复编码。实际上,双打有252-1 NaN,单打有223-1 NaN。:p
哦,忘了减去无穷大了。

1tuwyuhd

1tuwyuhd7#

我了解到的这个问题的粗略估计版本是,32位浮点数给予5位精度,64位浮点数给予15位精度。当然,这取决于浮点数的编码方式,但这是一个很好的起点。

相关问题