algorithm - 如何最好地总结大量 float ?

标签 algorithm language-agnostic floating-point precision

假设您有一大堆各种大小的 float 。计算总和的最正确方法是什么,错误最少?例如,当数组看起来像这样时:

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

然后你用一个简单的循环从左到右相加,比如

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

每当你加起来时,较小的数字可能会低于精度阈值,因此误差会越来越大。据我所知,最好的方法是对数组进行排序并开始将数字从最低到最高相加,但我想知道是否有更好的方法(更快、更精确)?

编辑:感谢您的回答,我现在有一个工作代码可以完美地总结 Java 中的 double 值。它是获胜答案的 Python 帖子的直接移植。该解决方案通过了我所有的单元测试。 (这里有更长但优化的版本 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;
    }
}

最佳答案

对于“更精确”:this recipe in the Python Cookbook具有保持完整精度的求和算法(通过跟踪小计)。代码是用 Python 编写的,但即使您不了解 Python,它也足够清晰,可以适应任何其他语言。

this paper 中提供了所有详细信息.

关于algorithm - 如何最好地总结大量 float ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/394174/

相关文章:

algorithm - 逆向工程贝塞尔曲线

sql - 转换为 float : CAST vs CONVERT vs *1. 0

c++ - 为什么 `precise`限定符不生效?

java - 在 Java 中将节点添加到列表的开头?

algorithm - 为什么 Java 中的 Math.random() 返回 [0, 1) 中的 double 而不是其他间隔?

language-agnostic - "program to an interface"是什么意思?

unit-testing - 如何发送 RST 而不是正常关闭以进行测试?

php - 使用 "<="或 ">="比较 float 是否理想?

java - 从多个列表中获取值的所有组合

algorithm - 平台游戏 - 一种逼真的寻路算法