【问题标题】:Very large differences using float and double使用 float 和 double 的差异很大
【发布时间】:2016-11-29 15:43:42
【问题描述】:
#include <iostream>

using namespace std;

int main() {
    int steps=1000000000;
    float s = 0;
    for (int i=1;i<(steps+1);i++){
       s +=  (i/2.0) ; 
    }
    cout << s << endl;
}

s 声明为float:9.0072e+15

s 声明为double:2.5e+17(与在 Julia 中实现的结果相同)

我知道doublefloat 具有双精度,但float 仍应处理高达 10^38 的数字。

我确实读过类似的主题,但结果不一样,但在那种情况下差异非常小,这里的差异是 25 倍。

我还补充说,使用long double 可以得到与double 相同的结果。如果问题是精度,我本来希望有一些不同的东西。

【问题讨论】:

  • 您正在添加错误 1000000000 次。这是一个巨大的数字,所以大的偏差也不足为奇。
  • float mantissa 24 bits 表示2^24 = 16777216以上的一些整数会有错误。因此,对于float,您添加了 1.7% + 一些中间数字而没有任何错误,其余部分偏离了轨道。 64 位浮点具有整数精度,53 位尾数最多为 9007199254740992,这超出了您的限制。
  • 如果您想要浮点数的精确总和,请使用其他算法,例如 Kahan summation。

标签: c++ precision


【解决方案1】:

问题在于精度不够:https://en.wikipedia.org/wiki/Floating_point

在 1 亿个数字之后,您将 1e8 加到 1e16(或至少是那个数量级的数字),但单精度数字只能精确到 7 位 - 所以它与将 0 加到 1e16 相同;这就是为什么浮点数的结果要低得多。

在大多数情况下,首选双精度而不是浮点数。

【讨论】:

    【解决方案2】:

    浮点精度问题!无限实数不可能用计算机的有限内存来表示。一般来说,浮点数只是它们要表示的数字的近似值。

    有关详细信息,请查看以下文档: https://softwareengineering.stackexchange.com/questions/101163/what-causes-floating-point-rounding-errors

    【讨论】:

      【解决方案3】:

      您没有提及您使用的是哪种类型的浮点数,但我假设您使用的是 IEEE 754 或类似标准。

      我知道 double 具有双精度

      为了更准确使用术语,double 使用两倍的位。尽管被命名为“双精度”,但这并不是可表示值数量的两倍,而是可表示值的 4294967296 倍。

      但 float 仍应处理最多 10^38 的数字。

      Float 可以处理几个数量级的数字。但这并不意味着该范围内的浮点值是精确的。例如,3,4028235E+38 可以表示为单精度浮点数。您认为浮点数表示的先前值之间的差异有多大?是机器ε吗?也许0.1?也许1?不,相差大约2E+31。

      现在,您的数字不在这个范围内。但是,它们超出了可以用浮点数精确表示的整数的连续范围。该范围内的最高值恰好是 16777217,或大约 1.7E+7,远小于 2.5E+17。因此,超出该范围的每次添加都会给结果增加一些错误。你执行了十亿次计算,所以这些错误加起来。


      结论:

      • 了解单精度远不如双精度精度。
      • 避免可能累积精度误差的长序列计算。

      【讨论】:

        猜你喜欢
        • 2012-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-18
        • 2013-09-25
        • 2020-11-22
        • 2019-09-25
        • 2018-11-30
        相关资源
        最近更新 更多