![](/img/trans.png)
[英]Why adding from biggest to smallest floating-point numbers is less accurate than adding from smallest to biggest?
[英]Biggest possible rounding error when computing floating-point numbers
我正在用 Java 开发一个时间关键算法,因此没有使用BigDecimal
。 为了处理舍入误差,我设置了一个误差上限,低于该上限的不同浮点数被认为是完全相同的。 现在的问题是这个界限应该是什么? 或者换句话说,在使用浮点数(浮点加法、减法、乘法和除法)执行计算操作时,可能出现的最大舍入误差是多少?
通过我所做的实验,似乎1e-11
的界限就足够了。
PS:这个问题与语言无关。
编辑:我使用double
数据类型。 这些数字是用Random
的nextDouble()
方法生成的。
编辑 2:看来我需要根据我使用的浮点数的生成方式来计算错误。 nextDouble()
方法如下所示:
public double nextDouble() {
return (((long)(next(26)) << 27) + next(27))
/ (double)(1L << 53); }
基于此方法中的常量,我应该能够计算出使用此方法生成的浮点数可能发生的最大错误(它的机器 epsilon ?)。 如果有人可以发布计算结果会很高兴。
单个简单运算的最坏情况舍入误差是包含运算实数结果的一对双精度值之间差距的一半。 Random 的 nextDouble 方法的结果是“ 从范围 0.0d(含)到 1.0d(不含) ”。 对于这些数字,最大的差距约为 1e-16,最坏情况下的舍入误差约为 5e-17。
这是一个打印一些样本数的差距的程序,包括 Random 的 nextDouble 的最大结果:
public class Test {
public static void main(String[] args) {
System.out.println("Max random result gap: "
+ Math.ulp(Math.nextAfter(1.0, Double.NEGATIVE_INFINITY)));
System.out.println("1e6 gap: "
+ Math.ulp(1e6));
System.out.println("1e30 gap: "
+ Math.ulp(1e30));
}
}
输出:
Max random result gap: 1.1102230246251565E-16
1e6 gap: 1.1641532182693481E-10
1e30 gap: 1.40737488355328E14
根据您正在执行的计算,错误可能会在多次操作中累积,从而产生比您从这种简单的单操作方法中预测的更大的总舍入误差。 正如 Mark Dickinson 在评论中所说,“数值分析比这要复杂一些。”
这取决于:
例如,考虑函数f(x) = a * ( b - ( c+ d))
没什么大不了的,或者是吗?
事实证明它是当 d << c, b = c 和 a 什么的时候,但我们只是说它很大。
让我们说:
a = 10e200
b = c = 5
d = 10e-90
这完全是编造的,但你明白了。 关键是,c 和 d 之间的幅度差异意味着
c + d = c (small rounding error because d << c)
b - (c + d) = 0 (should be 10e-90)
a * (b - (c + d)) = 0 (where it really should be 10e110)
长话短说,一些运算(特别是减法)(可以)杀死你。 此外,您需要查看的不是生成函数,而是您对数字(您的算法)进行的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.