为什么在浮点中从大到小会引入更多的误差
Why adding big to small in floating point introduce more error?
不知道为什么,但如果我把大到小的fp数字相加,增量误差似乎更大:
#include <iostream>
#include <math.h>
int main() {
std::cout.precision(50);
const int numLoops = 1000;
const long length = 10000;
const double rate = 0.1;
long totalLength = length * numLoops;
long long steps = (long long)(totalLength / rate);
double sum = 0.0;
double sumRemainder = 0.0;
for (long long step = 0; step < steps; step++) {
if (sumRemainder >= length) {
sumRemainder = fmod(sumRemainder, length);
}
sum += rate;
sumRemainder += rate;
}
std::cout << " length: " << length << std::endl;
std::cout << " num loops: " << numLoops << std::endl;
std::cout << " rate: " << rate << std::endl;
std::cout << " steps: " << steps << std::endl << std::endl;
std::cout << " sum: " << sum << std::endl;
std::cout << " sum remainder: " << sumRemainder << std::endl;
std::cout << " error: " << abs(totalLength - sum) << std::endl;
std::cout << " error remainder: " << abs(length - sumRemainder) << std::endl;
std::cout << std::endl;
}
这两个和之间唯一的区别是,一个是所有步骤,而另一个是,一旦达到极限,我就简单地计算结果(因此,它会钳制到一个小值(:
sumRemainder = fmod(sumRemainder, length);
这似乎是它在求和相同数量时引入低误差的原因:1.884836819954216480255126953125e-05
与0.01887054927647113800048828125
有人能用一个聪明的例子向我解释为什么会发生这种情况吗?
要处理大数字或小数字,浮点格式可缩放数字。一个数字的有效位使用固定数量的数字,这些数字按某个基数(通常为2(的幂进行缩放,称为指数。还有一个符号、+或−,尽管该符号有时包含在有效位中。
例如,使用二进制格式,1.0112的有效位在用零指数缩放时表示1+3/16(1.0112>20=1+3/16(,在用四指数缩放时代表11(1.011>sub>2 <2>4*<sub=−1>有效位有固定数量的数字。所以只有特定的数字可以表示。当执行任何算术运算时,精确的数学结果将四舍五入到最接近的可表示数。(舍入的常见默认规则是舍入到最接近的可表示值,在平局的情况下,舍入到最低位数为偶数。( 例如,在有效位中有三位小数的十进制格式中,考虑将数字567(5.67•102(和789(7.89•102>(相加。结果是1356,但位数太多。因此,它被四舍五入到1360(1.36•103(。四舍五进误差为4。 因此,当使用浮点数时,会出现舍入误差,这些误差是有效位中最低有效位位置值的一小部分。当数字的指数较大时,可能的误差也较大。误差总是在零和最低有效数字位置值的一半之间(因为两个可表示数字之间的任何数字要么在中点,要么更接近一个或另一个,所以从来没有必要移动一个数字超过可表示数字间距离的一半。( 因此,当使用较大的数字时,舍入误差较大。
- 为什么在浮点中从大到小会引入更多的误差
- 通过 Rcpp 和 bit64 R 包将最大的int64_t变量值从 C++ 传递到 R
- 如何将较大数字中从0到9的单个数字放入只包含数字的数组中
- QT-如何通过按下按钮从子窗口小部件返回到父窗口小部件
- 从大范围内生成一个随机数,但从大范围的中间开始生成较小的范围
- 从C 到C#调用INT []显示随机大数字,而不是原始数组成员
- 如何从大到小组织数组中的前 10 个常用值
- 从字符串到基数 2 的 JavaScript 大整数
- QDial 设置范围从 0.00 到 10.00 到小部件显示
- C 如何从向量到给定数字的向量中找到最小元素数量
- 根据其在C 中的存储值从最大到最少的地图
- 在 c++ 中从字符串到 int 的大数字
- 从大整数 ZZ(如 NTL 中声明)到十六进制
- 排序类对象数据成员从大到小
- 从毫米到公里的转换(以较小的单位溢出,例如米)
- 大括号初始化函数指针数组:从 'void (*(*)())()' 到 'void (*)()' 的转换无效
- 数组和 For 循环:创建从大到小的数字列表
- C++数组从最大到最小的数字
- 如何移动数组中的元素,将奇数放到数组的开头(从最小到最大),甚至放到后面(从最大到最小)
- 使用Std::vector::reserve时,Std::sort顺序从大到小