【发布时间】:2012-11-05 05:48:45
【问题描述】:
我知道a similar question,但我想征求人们对我的算法的意见,以尽可能准确地将浮点数与实际成本相加。
这是我的第一个解决方案:
put all numbers into a min-absolute-heap. // EDIT as told by comments below
pop the 2 smallest ones.
add them.
put the result back into the heap.
continue until there is only 1 number in the heap.
这个需要 O(n*logn) 而不是正常的 O(n)。真的值得吗?
第二种解决方案来自我正在处理的数据的特征。 这是一个巨大的正数列表,数量级相似。
a[size]; // contains numbers, start at index 0
for(step = 1; step < size; step<<=1)
for(i = step-1; i+step<size; i+=2*step)
a[i+step] += a[i];
if(i < size-1)
a[size-1] += a[i];
基本思想是以“二叉树”方式求和。
注意:这是一个伪 C 代码。 step<<=1 表示乘以 2。
这个需要 O(n)。
我觉得可能有更好的方法。你能推荐/批评吗?
【问题讨论】:
-
您似乎隐含地假设要求和的数字是正数。如果它们可以具有不同的符号,则策略将类似于“如果可能,将最小幅度和符号与当前计数相反的数量添加”。
-
元素会按升序放入堆中,所以你可以使用两个队列来代替。如果数字是预先排序的,这会产生
O(n) -
在选择算法时,请考虑以下一组数字:
{DBL_MAX, 1, -DBL_MAX}。如果你的算法所做的只是决定将数字相加的顺序,那么它会得到不正确的答案0,除非它首先添加两个 large 数字,在这种情况下它会得到正确的答案@987654328 @。因此,对于该特定输入,您的最小堆会失败,因为这件事对这项工作进行了大多数启发式方法。我认为 Kahan 是对的。 -
@AShelly 我的第二个算法不是 O(N lg N) 而是 O(N) 因为在第一个“步进循环”中它增加了 N/2 次,第二次增加了 N/4 次,第三次加N/8次,以此类推
-
@AShelly:
n + n/2 + n/4 + n/8 + ... = 2*n
标签: algorithm floating-point sum floating-accuracy