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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.