Lists: Converting Double to Single
duncan.booth at invalid.invalid
Fri Mar 2 10:22:50 CET 2007
Jussi Salmela <tiedon_jano at hotmail.com> wrote:
> I've run a couple of tests and it seems to me that Dennis Lee Bieber
> on the trail of the truth when he claims that smallest magnitude to
> the largest is the way to do the summation. Actually it isn't THE way
> although it diminishes the error. I was sort of astonished because I
> also had somewhere along the years formed the same notion as Dennis.
> "Your" pairwise method beats the former method by a large margin
> although I don't understand why. To tell you the truth: I started out
> show you were wrong because intuitively (for me at least) the former
> method should work better than yours.
I think Dennis is spot on when he says that smallest to largest is the
best way. What he has missed though is that if you have a list of
similar sized values, then after you have added the first two together
the next addition still needs to follow the smallest to largest rule so
it shouldn't include the result of the first addition. One option, if
you have access to the full list when you start, would be to reinsert
each partial sum back into the sorted list as you calculate it: a heap
queue might be an appropriate implementation for that.
The pairwise sum gives you most, although not quite all, of the benefit
of sorting the data: obviously if the input values are identical it is
almost exactly equivalent to adding the smallest values and then
inserting the partial result back into the list. Even in the 1000000,
0.00001 case it avoids most of the precision-losing additions such as
500000000005.0 + 0.00001 which the simple sum hits.
Also it has the further advantages of still working with other summable
objects (e.g. lists) so long as they are associative and not requiring
you to know all the values or even the length of the sequence in
For floating point you can of course use methods to preserve the lost
bits such as the kahan sum, or even just do all imtermediate
calculations to a higher internal precision.
By the way, I found another bug in my sumpairs: += is a very bad idea
here if the input can contain mutables, so the relevant line should be:
tmp[-1] = tmp[-1] + v
Once I fixed that one, so it no longer attempts to modify lists in-
place, it appears that the more balanced intermediate results give a
benefit when summing lists as well. sumpairs on a list of lists seems to
beat the builtin sum as soon as the length of the list exceeds about 210
items. At 1000 items it is about 3 times faster and 30 times faster at
10,000 items. If I get the time I think I really should code up a C
version of sumpairs and see how that compares against Pythons builtin
sum for numerical sums.
I guess either everyone else missed that computer science lecture I
thought I remembered, or maybe I was the one who was asleep and I
dreamed it all. :)
More information about the Python-list