如何最好地总结了大量的浮点数?浮点数、总结了

2023-09-10 23:45:24 作者:苏辞

假设你有一个大阵浮各种大小的点号码,。什么是计算的总和,用最少的错误最正确的方法是什么?例如,当阵列是这样的:

  [1.0,1E-10,1E-10,... 1E-10.0]
 

和你从左边加起来正确的一个简单的循环,像

 和= 0
numbers.each做| VAL |
    总和+ = VAL
结束
 

当添加了更小的数字可能低于precision阈值,误差会越来越大。据我所知道的最好的办法就是数组排序,并开始增加从最低到最高的数字,但我想知道如果有一个更好的方法(更快,更precise)?

SQL注入总结

修改:感谢您的回答,我现在有一个工作code,它完美地总结了双值在Java中。距离获胜答案Python的后直口。该解决方案通过了所有的我的单元测试。 (这方面的一个长,但优化后的版本可以在这里找到Summarizer.java)

  / **
 *添加了数字与完美的precision阵列,并在为O(n)。
 *
 * @see HTTP://$c$c.activestate.com/recipes/393090/
 * /
公共类摘要生成{

    / **
     *完美总结数字,没有舍入误差(如果可能)。
     *
     * @参数值
     *值来总结。
     * @返回的总和。
     * /
    公共静态双MSUM(双...值){
        名单<双>谐音=新的ArrayList<双>();
        对于(双X:值){
            INT I = 0;
            对于(双Y:谐音){
                如果(Math.abs(X)< Math.abs(Y)){
                    双TMP = X;
                    X = Y;
                    Y = TMP;
                }
                双HI = X + Y;
                双罗= Y  - (喜 -  X);
                如果(罗!= 0.0){
                    partials.set(我,LO);
                    ++我;
                }
                X =喜;
            }
            如果(ⅰ&其中; partials.size()){
                partials.set(I,X);
                。partials.subList(我+ 1,partials.size())清();
            } 其他 {
                partials.add(X);
            }
        }
        返回总和(谐音);
    }

    / **
     *总结了部分数字不能概括没有休息
     *的precision损失。
     * /
    公共静态双总和(集<双>的值){
        双S = 0.0;
        对于(双D:值){
            S + = D;
        }
        返回S;
    }
}
 

解决方案

有关更多precise:这个配方在Python食谱具有求和算法,它保持了完整的precision(通过跟踪小计)。 code是在Python,但即使你不知道的Python它很清楚,以适应任何其他语言。

所有的细节在本文。

Imagine you have a large array of floating point numbers, of all kinds of sizes. What is the most correct way to calculate the sum, with the least error? For example, when the array looks like this:

[1.0, 1e-10, 1e-10, ... 1e-10.0]

and you add up from left to right with a simple loop, like

sum = 0
numbers.each do |val|
    sum += val
end

whenever you add up the smaller numbers might fall below the precision threshold so the error gets bigger and bigger. As far as I know the best way is to sort the array and start adding up numbers from lowest to highest, but I am wondering if there is an even better way (faster, more precise)?

EDIT: Thanks for the answer, I now have a working code that perfectly sums up double values in Java. It is a straight port from the Python post of the winning answer. The solution passes all of my unit tests. (A longer but optimized version of this is available here Summarizer.java)

/**
 * Adds up numbers in an array with perfect precision, and in O(n).
 * 
 * @see http://code.activestate.com/recipes/393090/
 */
public class Summarizer {

    /**
     * Perfectly sums up numbers, without rounding errors (if at all possible).
     * 
     * @param values
     *            The values to sum up.
     * @return The sum.
     */
    public static double msum(double... values) {
        List<Double> partials = new ArrayList<Double>();
        for (double x : values) {
            int i = 0;
            for (double y : partials) {
                if (Math.abs(x) < Math.abs(y)) {
                    double tmp = x;
                    x = y;
                    y = tmp;
                }
                double hi = x + y;
                double lo = y - (hi - x);
                if (lo != 0.0) {
                    partials.set(i, lo);
                    ++i;
                }
                x = hi;
            }
            if (i < partials.size()) {
                partials.set(i, x);
                partials.subList(i + 1, partials.size()).clear();
            } else {
                partials.add(x);
            }
        }
        return sum(partials);
    }

    /**
     * Sums up the rest of the partial numbers which cannot be summed up without
     * loss of precision.
     */
    public static double sum(Collection<Double> values) {
        double s = 0.0;
        for (Double d : values) {
            s += d;
        }
        return s;
    }
}

解决方案

For "more precise": this recipe in the Python Cookbook has summation algorithms which keep the full precision (by keeping track of the subtotals). Code is in Python but even if you don't know Python it's clear enough to adapt to any other language.

All the details are given in this paper.