【问题标题】:Floating-point arithmetic: why would order of addition matter?浮点运算:为什么加法的顺序很重要?
【发布时间】:2018-02-23 23:51:32
【问题描述】:

我知道不可能用有限的位数将所有数字表示为任意精度,并且不建议对浮点数进行幼稚的比较。但我希望,如果我将许多数字相加,那么添加它们的 ** order ** 并不重要。

为了测试这个预测,我创建了一个随机数向量并计算它们的总和,然后对向量进行排序并再次计算总和。很多时候,这两个总和不匹配!这是我的代码(包括在下面)的问题,是浮点运算的一般缺点,还是可以通过切换编译器等解决的问题?

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <random>
#include <vector>

double check_sum_depends_on_order(int seed)
{
    // fill a vector with random numbers
    std::vector<long double> v;
    std::uniform_real_distribution<long double> unif(-1.,1.);
    std::mt19937 rng(seed);
    for (size_t i = 0; i < 1000; ++i)
    {
        v.push_back(unif(rng));
    }

    // copy this vector and then shuffle it
    std::vector<long double> v2 = v;
    std::sort(v2.begin(), v2.end());


    // tot is running total for vector v, unsorted
    // tot2 is running total for vector v2, sorted
    long double tot = 0.0, tot2 = 0.0;
    for (size_t i = 0; i < v.size(); ++i)
    {
        tot += v[i];
        tot2 += v2[i];
    }

    // display result
    // you can comment this if you do not want verbose output
    printf("v tot\t= %.64Lf\n", tot);
    printf("v2 tot\t= %.64Lf\n", tot2);
    printf("Do the sums match (0/1)? %d\n\n", tot==tot2);

    // return 1.0 if the sums match, and 0.0 if they do not match
    return double(tot==tot2);
}

int main()
{
    // number of trials
    size_t N = 1000;

    // running total of number of matches
    double match = 0.;
    for (size_t i = 0; i < N; ++i)
    {
        // seed for random number generation
        int seed = time(NULL)*i;
        match += check_sum_depends_on_order(seed);
    }

    printf("%f percent of random samples have matching sums after sorting.", match/double(N)*100.);
    return 0;
}

【问题讨论】:

  • “但我希望如果我将许多数字加在一起,我添加它们的**顺序**无关紧要。” - 我不明白你为什么会这么想。
  • 由于准确性可能丢失,每次将两个数字相加时,我不希望它们是完全相同的值。精度损失的数量不同 - 取决于添加的值。不同的顺序意味着沿途不同地方的准确性损失不同。
  • 这是一个更简单的例子:ideone.com/J9SSdT
  • 但是我希望如果我将许多数字加在一起,我添加它们的顺序并不重要。 -- 现在你知道为什么它是时间和再次不要比较浮点值是否相等。当您看到值不相等时,除了加法之外,还有其他情况会让您感到惊讶。
  • 我不认为这是重复的,但它确实提供了一个潜在的原因,说明它不能按 OP 预期的方式工作。

标签: c++ floating-point precision


【解决方案1】:

假设您有一个精度为三位的十进制浮点类型。不太现实,但它是一个更简单的例子。

假设您有三个变量,abc。假设a1000bc 都是14

a + b 将是 1014,向下舍入为 1010。(a + b) + c 将是 1024,向下舍入为 1020。

b + c 将是 28。a + (b + c) 将是 1028,四舍五入到 1030。

【讨论】:

  • 我经常发现类比是最好的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 2017-06-27
相关资源
最近更新 更多