使用 float 和 double 的差异很大

Very large differences using float and double

#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 相同。如果问题是精度,我希望会有一些不同。

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

在 1 亿个数字之后,您要将 1e8 添加到 1e16(或至少该数量级的数字),但单精度数字仅精确到 7 位数字 - 因此它与将 0 添加到 1e16 相同;这就是为什么您的浮动结果要低得多的原因。

在大多数情况下更喜欢双倍浮动。

你没有提到你使用的是什么类型的浮点数,但我假设你使用的是 IEEE 754 或类似的。

I understand double has double precision

为了更精确 术语,double 使用两倍的位数。这不是可表示值数量的两倍,它是可表示值数量的 4294967296 倍,尽管被命名为 "double precision".

but float should still handle numbers up to 10^38.

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

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


结论:

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

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

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