Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accurate evaluation of 1/1 + 1/2 + ... 1/n row

Tags:

c++

sum

ieee-754

I need to evaluate the sum of the row: 1/1+1/2+1/3+...+1/n. Considering that in C++ evaluations are not complete accurate, the order of summation plays important role. 1/n+1/(n-1)+...+1/2+1/1 expression gives the more accurate result. So I need to find out the order of summation, which provides the maximum accuracy. I don't even know where to begin. Preferred language of realization is C++. Sorry for my English, if there are any mistakes.

like image 781
Michael Pankov Avatar asked Aug 08 '09 12:08

Michael Pankov


4 Answers

For large n you'd better use asymptotic formulas, like the ones on http://en.wikipedia.org/wiki/Harmonic_number;

alt text

Another way is to use exp-log transformation. Basically:

H_n = 1 + 1/2 + 1/3 + ... + 1/n = log(exp(1 + 1/2 + 1/3 + ... + 1/n)) = log(exp(1) * exp(1/2) * exp(1/3) * ... * exp(1/n)).

Exponents and logarithms can be calculated pretty quickly and accuratelly by your standard library. Using multiplication you should get much more accurate results.

If this is your homework and you are required to use simple addition, you'll better add from the smallest one to the largest one, as others suggested.

like image 148
liori Avatar answered Nov 12 '22 13:11

liori


The reason for the lack of accuracy is the precision of the float, double, and long double types. They only store so many "decimal" places. So adding a very small value to a large value has no effect, the small term is "lost" in the larger one.

The series you're summing has a "long tail", in the sense that the small terms should add up to a large contribution. But if you sum in descending order, then after a while each new small term will have no effect (even before that, most of its decimal places will be discarded). Once you get to that point you can add a billion more terms, and if you do them one at a time it still has no effect.

I think that summing in ascending order should give best accuracy for this kind of series, although it's possible there are some odd corner cases where errors due to rounding to powers of (1/2) might just so happen to give a closer answer for some addition orders than others. You probably can't really predict this, though.

like image 33
Steve Jessop Avatar answered Nov 12 '22 12:11

Steve Jessop


I don't even know where to begin.

Here: What Every Computer Scientist Should Know About Floating-Point Arithmetic

like image 5
Marc Mutz - mmutz Avatar answered Nov 12 '22 12:11

Marc Mutz - mmutz


Actually, if you're doing the summation for large N, adding in order from smallest to largest is not the best way -- you can still get into a situation where the numbers you're adding are too small relative to the sum to produce an accurate result.

Look at the problem this way: You have N summations, regardless of ordering, and you wish to have the least total error. Thus, you should be able to get the least total error by minimizing the error of each summation -- and you minimize the error in a summation by adding values as nearly close to each other as possible. I believe that following that chain of logic gives you a binary tree of partial sums:

Sum[0,i] = value[i]

Sum[1,i/2] = Sum[0,i] + Sum[0,i+1]

Sum[j+1,i/2] = Sum[j,i] + Sum[j,i+1]

and so on until you get to a single answer.

Of course, when N is not a power of two, you'll end up with leftovers at each stage, which you need to carry over into the summations at the next stage.

(The margins of StackOverflow are of course too small to include a proof that this is optimal. In part because I haven't taken the time to prove it. But it does work for any N, however large, as all of the additions are adding values of nearly identical magnitude. Well, all but log(N) of them in the worst not-power-of-2 case, and that's vanishingly small compared to N.)

like image 3
Brooks Moses Avatar answered Nov 12 '22 13:11

Brooks Moses