计算浮点数时可能出现的最大舍入误差

时间:2015-06-17 05:30:05

标签: java floating-point rounding floating-accuracy rounding-error

我正在使用Java开发时间关键算法,因此我没有使用BigDecimal。为了处理舍入误差,我设置了一个上限误差,低于该值时,不同的浮点数被认为是完全相同的。现在问题是该应该是什么?换句话说,当使用浮点数(浮点加法,减法,乘法和除法)执行计算操作时,可能发生的最大舍入误差是什么?

通过我已经完成的实验,似乎1e-11的界限就足够了。

PS:此问题与语言无关。

编辑:我正在使用double数据类型。这些数字是使用Random的{​​{1}}方法生成的。

编辑2:似乎我需要根据我正在使用的浮点数如何生成来计算错误。 nextDouble()方法如下所示:

nextDouble()

基于此方法中的常量,我应该能够计算出使用此方法生成的浮点数可能发生的最大错误(其 machine epsilon ?)。如果有人可以发布计算,我会很高兴。

2 个答案:

答案 0 :(得分:2)

单个简单操作的最坏情况舍入误差是包含操作的实数结果的一对双精度之间的差距的一半。 Random的nextDouble方法的结果是" from the range 0.0d (inclusive) to 1.0d (exclusive)"。对于这些数字,最大差距约为1e-16,最差情况舍入误差约为5e-17。

这是一个打印一些样本数的差距的程序,包括Random的最大结果:

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在评论中所说,"数值分析比这更复杂。"

答案 1 :(得分:0)

这取决于:

  1. 您的算法
  2. 涉及数量的大小
  3. 例如,考虑函数f(x) = a * ( b - ( c+ d)) 没什么大不了的,不是吗?

    事实证明,当d <&lt; c,b = c和其他什么,但我们只能说它很大。

    让我们说:

    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)
    

    长话短说,一些操作(特别是减法)(可以)杀了你。此外,您需要查看的是生成函数,而不是使用数字(您的算法)执行操作