Does this help?
use Data::Dumper; # print "2718281828459045235360287471352662497757247093699\n"; sub e{ @e=(1)x pop; for(1..@e){ print "Before: ", Dumper \@e; for(reverse(1..$#e)){ printf "Add %3.3f/%d(%3.3f) to \$e[%d] (now %3.3f); ", $e[$_],$_, $e[$_]/$_, $_-1, ($e[$_-1]+ $e[$_]/$_); $e[$_-1]+=$e[$_]/$_; printf "Set \$e[%d] = %d (10*(%d%%%d))\n", $_, 10*($e[$_]%$_), $e[$_], $_; $e[$_]=10*($e[$_]%$_); } print "After: ", Dumper \@e; printf "Printing: %d\n\n", $e[0]; $e[0]=0 } } e(5);
OK so lets have a look at the results:
Before: $VAR1 = [ 1, 1, 1, 1, 1 ];
Simple enough so far, we have an array of ones. Now we start the calculations. As you correctly surmised we are working from the inside out, and we are looking at calculating only a single digit of the value at a time. The first bit is easy enough to understand. In fact this just implements the calculation e=1+1+1/2(1+1/3(1+1/4))). This will not give us a very accurate value for e but it will show you how we are walking the digits.
Add 1.000/4(0.250) to $e[3] (now 1.250); Set $e[4] = 10 (10*(1%4)) Add 1.250/3(0.417) to $e[2] (now 1.417); Set $e[3] = 10 (10*(1%3)) Add 1.417/2(0.708) to $e[1] (now 1.708); Set $e[2] = 10 (10*(1%2)) Add 1.708/1(1.708) to $e[0] (now 2.708); Set $e[1] = 0 (10*(1%1)) After: $VAR1 = [ '2.70833333333333', 0, 10, 10, 10 ]; Printing: 2
So you can probably understand how we get the first digit without too much problem. What about those pesky decimals and how are we walking down them. The key is that we have been leaving some data behind with the $e[$_]=10*($e[$_]%$_). So what is that all about? Well it is a bit tricky. Look at the numbers left in the array 0, 0, 10, 10, 10. You can see them here and then what happens to them:
Before: $VAR1 = [ 0, 0, 10, 10, 10 ]; Add 10.000/4(2.500) to $e[3] (now 12.500); Set $e[4] = 20 (10*(10%4 +)) Add 12.500/3(4.167) to $e[2] (now 14.167); Set $e[3] = 0 (10*(12%3) +) Add 14.167/2(7.083) to $e[1] (now 7.083); Set $e[2] = 0 (10*(14%2)) Add 7.083/1(7.083) to $e[0] (now 7.083); Set $e[1] = 0 (10*(7%1)) After: $VAR1 = [ '7.08333333333333', 0, 0, 0, 20 ]; Printing: 7
OK, so what just happened? Well you can see that we have the exact same digits 7083333 as we had originally but the first digit is gone. The 10* we use on the storage stage is designed so we get the number we want in a form that int(num) will release. The modulus operator is being used to store the remainder digits (in fact we are storing exactly the part after the decimal point that is not being printed). And the number itself, why is it the right one? Well we are using bits of number theory. We are effectively storing the digit we want across multiple bases and using a continuing fraction (I am not a mathermatician but I think they are the correct terms). Rather than try to explain it in symbols (not sure that I could anyway) lets just eyeball it.
Before: $VAR1 = [ 0, 0, 10, # big bit 10, # medium bit 10 # small bit ]; Printing: 7(.0833) Before: $VAR1 = [ 0, 0, 0, # big bit 0, # medium bit 20 # small bit ]; Printing: 0(.8333) Before: $VAR1 = [ 0, 0, 10, # big bit 20, # medium bit 0 # small bit ]; Printing: 8(.333) Before: $VAR1 = [ 0, 0, 0, # bit bit 20, # medium bit 0 # small bit ]; After: $VAR1 = [ '3.33333333333333', 0, 0, 20, # note medium bit same as before 0 ]; Printing: 3(.333)
As you can see what we have is a representation of the digits we want to print. If we have lots of small bits we have a small number, a small+med+big is a bigger number. med+med+big > small+med+big.
No doubt one of our resident mathematicians can give you a better analysis but using high school algebra we can write:
Where b = big, m = medium, s= small 10b + 10m + 10s = 7.08333 - 1 20s = 0.8333 - 2 10b + 20m = 8.333 - 3 20m = 3.333 - 4 From 3 & 4 we can say 10b = 5 From 4 we can say 10m = 1.6666 From 2 we can say 10s = 0.41666
So we are storing the remainder in base format where the base is non integer.
cheers
tachyon
In reply to Re: Caclulation of e
by tachyon
in thread Caclulation of e
by doc
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |