代码之家  ›  专栏  ›  技术社区  ›  mauriciopastrana

谷歌计算器故障,浮动对双重可能是一个原因?

  •  4
  • mauriciopastrana  · 技术社区  · 16 年前

    我这样做只是为了好玩(所以,不完全是一个问题,我已经看到了降级的发生),但是,代替了谷歌的新发现 inability math correctly (检查一下!根据google 500000000002-500000000001=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
    

    谷歌似乎在使用简单的32位浮点精度(这里的错误),如果在上面的代码中切换为双精度浮点,就可以解决这个问题!可以吗?

    /MP

    7 回复  |  直到 12 年前
        1
  •  2
  •   gil    16 年前

    在C中,尝试(double.maxvalue==(double.maxvalue-100)),您将得到正确的……

    但它应该是这样的:

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

    考虑到这一点,您有64位来表示一个大于2^64(double.maxvalue)的数字,因此可能会出现不准确的情况。

        2
  •  4
  •   Frank Krueger    16 年前

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

    When you change the insides, nobody notices

    计算的本质-算术 发动机-被完全扔掉 从头重写。这个 标准IEEE浮点库 被替换为 任意精度算法 图书馆。这是在人们 一直在写关于如何 Calc无法执行十进制运算 对,例如计算 10.21-10.2导致0.0100000000000016。

        3
  •  2
  •   DrPizza    16 年前

    谷歌似乎在使用简单的32位浮点精度(这里的错误),如果在上面的代码中切换为双精度浮点,就可以解决这个问题!可以吗?

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

        4
  •  1
  •   Derek Park    16 年前

    爱贝尔

    考虑到这一点,您有64位来表示一个大于2^64(double.maxvalue)的数字,因此可能会出现不准确的情况。

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

    浮点数的不精确性并非来自于大于 最大值 (这是不可能的,不包括 Double.PositiveInfinity )这是因为所需的值范围太大,不适合数据类型。因此,我们放弃了精度,以换取更大的有效范围。在Essense中,我们减少了有效数字以换取更大的指数范围。

    @ DrPizza

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

    真的。我没有解释重复编码。实际上有2个 五十二 -双打1分,双打2分 二十三 -不过,单身人士要1个奶奶。P

        5
  •  0
  •   DrPizza    16 年前

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

    甚至不是;IEEE编码对相同的值使用多个编码。具体来说,NaN由所有位-1的指数表示,然后 任何 尾数的非零值。因此,有2个 五十二 双打保姆,2人 二十三 单身的奶奶。

        6
  •  0
  •   DrPizza    16 年前

    真的。我没有解释重复编码。实际上双打有252-1个保姆,单打有223-1个保姆。P

    噢,忘了减去无穷大。

        7
  •  0
  •   John Meagher    16 年前

    我学到的这个问题的粗略估计版本是32位浮点给你5位精度,64位浮点给你15位精度。当然,这取决于如何对浮点数进行编码,但这是一个很好的起点。