以不同顺序添加相同的双打时,结果不同



为什么在添加相同数字时输出会有所不同?

public class Test {
    public static void main(String a[]) {
        double[] x = new double[]{3.9, 4.3, 3.6, 1.3, 2.6};
        System.out.println(">>>>>>> " + sum(x));
    }
    public static double sum(double[] d) {
        double sum = 0;
        for (int i = 0; i < d.length; i++) {
            sum += d[i];
        }
        return sum;
    }
}

输出是:15.7

,如果我互换值

double[] x = new double[] {2.6, 3.9, 4.3, 3.6, 1.3};

我的输出为: 15.700000000000001

如何获得相同的输出?

浮点数数字会随着更多操作而失去精度。通常,首先添加最小的数字,您可以获得最高的精度。(因此结果 die 取决于操作的顺序)

除了维护相同的操作顺序外,您还必须使用Strictfp在不同平台上获得相同的结果。

或更好的是,不要使用浮点:改用bigdecimal。

在一个浮点算术操作序列的每个步骤中,系统必须产生以浮点格式表示的结果。这可能会导致四舍五入错误,丢失了一些信息。

添加两个不同的幅度时,较大的幅度倾向于控制哪些必须掉落。如果您添加一个大数量和少量数量,则由于结果的幅度很大,因此少量数量的许多位将丢失在舍入错误中。添加相似幅度的数量时,这种效果会降低。首先添加几个小数字,将较大的数字留在末端,使小数的效果累积。

例如,考虑{ 1e17, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, -1e17 }。确切的答案无需任何舍入,将是147。在上面显示的顺序中添加112。每次添加" 21.0"必须舍入以适合1E17左右的数字。添加绝对幅度的上升顺序可得出144,更接近确切答案。添加7个小数的部分结果正好为147,然后必须将其四舍五入以适合1E17的数字。

简单地添加所有值将导致较长数组的误差相对较大(或更确切地说:当总和已经"大"时,错误将是"大",并且还应添加进一步的"小"数字)。

作为减少数值错误的一种可能性,您可以考虑http://en.wikipedia.org/wiki/kahan_summation_algorithm:

public static double kahanSum(double d[])
{
    double sum = 0.0;
    double c = 0.0;
    for (int i=0; i<d.length; i++)
    {
        double y = d[i] - c;
        double t = sum + y;
        c = (t - sum) - y;
        sum = t;
    }
    return sum;        
}

,因为执行操作时,双打和其他浮点数据类型必须处理四舍五入问题。精度不是无限的。如果您将10/3划分,结果为3.33333333 ...但是计算机存储只是此数字的一部分。

检查http://floating-point-gui.de/

相关内容

  • 没有找到相关文章

最新更新