J
James Kuyper
If we sort the above list as:
-HUGE_VAL, 0.0, DBL_EPSILON * 4., HUGE_VAL
The sum would be
s1 = -HUGE_VAL
s2 = -HUGE_VAL
s3 = -HUGE_VAL (because DBL_EPSILON * 4 is most certainly shifted out
completely by that addition)
s4 = 0.0
so in the end the sum would be 0. If we order it a bit differently, though:
-HUGE_VAL, HUGE_VAL, 0.0, DBL_EPSILON * 4
the sum comes around to DBL_EPSILON * 4 (so the mean would be DBL_EPSILON)
There doesn't appear to be an always perfect sorting algorithm for this
problem. At least none I can think of right now. We can't sort by
descending magnitude, because then the effect of the added carry values
might not appear.
Generally, we should try to sort in a way such that the magnitude of the
list sum is maximized... shouldn't we? Damn, what's the real goal here?
The following is not my idea, but I don't know who the true originator was.
Roundoff error is dominated by the magnitude of the larger item being
added. Therefore, you want to arrange as much cancellation as possible,
to keep the magnitudes small. At each step in the sum, add the item not
previously included which will make the next partial sum have the
smallest magnitude. One way to implement this is to sort the list, and
then set two pointers to point at the smallest positive and negative
values in that list. Add either the positive or negative value,
whichever is opposite to the sign of the current sum, moving the
corresponding pointer away from the other one. When either end of the
list is used up, add in the remaining items from the other end of the
list in order of increasing magnitude.