Floating-point arithmetic: why would order of addition matter?(浮点算术:加法顺序为什么重要?)
本文介绍了浮点算术:加法顺序为什么重要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我知道不可能用有限的位数来表示任意精度的所有数字,而且浮点数的天真比较也是不可取的。但我预计,如果我将许多数字相加在一起,我将它们相加的**顺序**并不重要。
为了测试这个预测,我创建了一个随机数向量并计算它们的和,然后对向量进行排序并再次计算和。通常情况下,这两个数字不匹配!这是我的代码(包括在下面)的问题,还是浮点算术的普遍缺陷,或者可能通过切换编译器等来解决的问题?
#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 = %.64Lf
", tot);
printf("v2 tot = %.64Lf
", tot2);
printf("Do the sums match (0/1)? %d
", 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;
}
推荐答案
假设您有一个精度为三位数的小数浮点类型。不太现实,但这是一个更简单的例子。
假设您有三个变量,a、b和c。假设a为1000,b和c均为14。
a + b将为1014,向下舍入为1010。(a + b) + c将为1024,向下舍入为1020。
b + c将是28岁。a + (b + c)将为1028,向上舍入为1030。
这篇关于浮点算术:加法顺序为什么重要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
织梦狗教程
本文标题为:浮点算术:加法顺序为什么重要?
基础教程推荐
猜你喜欢
- 通过引用传递 C++ 迭代器有什么问题? 2022-01-01
- GDB 显示调用堆栈上函数地址的当前编译二进制文 2022-09-05
- 为什么 RegOpenKeyEx() 在 Vista 64 位上返回错误代码 2021-01-01
- 为什么派生模板类不能访问基模板类的标识符? 2021-01-01
- 非静态 const 成员,不能使用默认赋值运算符 2022-10-09
- 为什么 typeid.name() 使用 GCC 返回奇怪的字符以及如 2022-09-16
- 我应该对 C++ 中的成员变量和函数参数使用相同的名称吗? 2021-01-01
- 如果我为无符号变量分配负值会发生什么? 2022-01-01
- 初始化列表*参数*评估顺序 2021-01-01
- CString 到 char* 2021-01-01
