7 Ada implementation of decimal representation of exp()

This is an Ada implementation of decimal representation of \(e\) based on SPIGOT algorithm for \(\pi \) by S. Rabinowitz & S. Wagon, The American Mathematical Monthly, March 1995.

This source file is here

-- More e digits trivia. 
-- Feel free to copy, distribute as long as this header attached so 
-- original algorithm creators and implementors are known. 
-- 
-- This is an Ada implementation of decimal representation of 'e' 
-- based on SPIGOT algorithm for \pi by 
-- S.  Rabinowitz & S. Wagon, _The_American_Mathematical_Monthly_, March 1995 
-- 
--  A C implementation of the above was posted on the net by 
--  Ed Hook 
--  MRJ Technology Solutions, Inc. 
--  NAS, NASA Ames Research Center 
--  Internet: hook@nas.nasa.gov 
-- 
-- This is an Ada implementation of the above using GNAT (gnu Ada compiler), 
-- with the added feature is that it computes the frequency of each digit in e, 
-- and computes the largest consecutive sequences of each digit within the 
-- expression that represents digits of e. 
-- 
-- the following is the result. my PC is still running trying to find the 
-- frequency for 200,000 digits and more for e, and it's been several days 
-- and not finished. So this is a partial results. (PC is 200 MHz pentium, 
-- running Linux 2.0.36, and compiler is GNAT 3.11p 
-- 
-- offcourse as number of digits of e goes very large, each digit is expected 
-- to show as often as any other digit. 
-- 
-- by Nasser M. Abbasi  nma@12000.org    feb. 20, 1999. 
-- 
-- results: 
 
-- this is distribution table for digits in e as function of how many 
-- digits. 
-- for example, when looking at 5000 digits of e, we find 497 0's, 
-- 478 1's, etc..  (this is for digits after the decimal point of e) 
-- 
-- 
--                                   #digits  in e 
--            -------------------------------------------------------------- 
--               500  5,000  20,000  50,000  200,000 
--            --------------------------------------------------------------- 
--how many 0's   51    497    1,949  4,948   19,916 
--how many 1's   43    478    2,010  5,055   20,367 
--how many 2's   50    492    2,020  4,969   19,794 
--how many 3's   53    514    2,080  5,026   20,071 
--how many 4's   52    470    1,989  4,966   20,082 
--how many 5's   44    478    1,979  5,046   20,038 
--how many 6's   51    545    2,057  5,133   20,221 
--how many 7's   60    525    1,977  4,959   19,817 
--how many 8's   40    509    1,966  4,972   19,939 
--how many 9's   56    492    1,974  4,926   19,755 
-- 
------------------------------------------------------------------------ 
--most occurring  '7'   '7'     '3'    '6'     '1' 
------------------------------------------------------------------------ 
--least occurring '8'   '4'     '0'    '9'     '9' 
------------------------------------------------------------------------ 
--difference 
--between largest 20   55      131    207     612 
--and smallest 
--in frequency 
------------------------------------------------------------------------ 
--difference 
--between largest 4%  1.1%   0.655%  0.414%  0.306% 
--and smallest 
--frequency in % 
-- 
-- 
--consecutive frequencies: under each column, there are 3 values, the first 
--is the number of digits that occurred next to each others for that digit, 
--and the start of this sub sequence, and its end, in position values. 
-- 
--for example, for 5,000 digits of e, we see that largest consecutive 
--sequence of digit '0' had length of 3, and it started at digit position 
--328 to position 330.  Digit positions are counted from left to right at 
--the decimal point.  for example e=2.718, here digit '7' is at position 1, 
--'1' is at position 2, etc.. 
-- 
--                                   #digits  in e 
--     ----------------+-----------------+----------------------------------- 
--          5,000      |   20,000        |    50,000         | 100,000 
--     ----------------+------------------+------------------+--------------- 
-- 0's   (3,328,330)   | (4,7688,7691)   |  *no change*      |(6,89296,89301) 
-- 1's   (3,427,429)   | (5,12220,12224) |  *no change*      | *no change* 
-- 2's   (2,2744,2746) | (4,17309,17312) |  (5,33483,33487)  | *no change* 
-- 3's   (4,3354,3375) |   *no change*   |  *no change*      | *no change* 
-- 4's   (3,787,789)   | (4,11806,11809) |  *no change*      | *no change* 
-- 5's   (4,3620,3623) |   *no change*   |  *no change*      | *no change* 
-- 6's   (5,4992,4996) |   *no change*   |  *no change*      | *no change* 
-- 7's   (4,1071,1074) |   *no change*   |  *no change*      | *no change* 
-- 8's   (4,723,726)   |   *no change*   |  *no change*      | *no change* 
-- 9's   (3,47,49)     |   *no change*   |  (4,29344,29347)  | *no change* 
-- 
-- 
-- 
--Compiler:    GNAT 3.11p , see http://www.adahome.com to download 
--To compile:  save this file as dist_e_final.adb and type 
--             gnatmake dist_e_final.adb 
--system:      Linux 2.0.36 
--Date:        feb. 17, 1999 
--To Run:      ./dist_e_final 
--             For example, to see e for 70 digits do: 
-- 
-- ./dist_e_final 70 
-- 2.7182818284590452353602874713526624977572470936999595749669676277240766 
-- frequency of  0 is  4 
-- frequency of  1 is  3 
-- frequency of  2 is  9 
-- frequency of  3 is  4 
-- frequency of  4 is  7 
-- frequency of  5 is  7 
-- frequency of  6 is  10 
-- frequency of  7 is  12 
-- frequency of  8 is  5 
-- frequency of  9 is  9 
-- 
-- performance note: On Pentium PRO 200 MHZ, using GNAT 3.11p, Linux 2.0.36, 
-- 128 MB RAM. No other activity on PC, and for 1,000,000 digits, this 
-- program will generate about 50 digits each minutes. So, for 1,000,000 
-- digits it will take about 13 days. for larger than 1,000,000 you might 
-- encounter stack overrun, depending on amount of memory you have... 
-- 
-- notice the main algorithm is O(n^2). 
-- 
 
with Ada.Text_Io;         use Ada.Text_Io; 
with ada.command_line;    use ada.command_line; 
 
procedure Dist_E_final is 
   type E_Type is array( Natural range <> ) of Natural; 
   Distribution : array(0..9) of Natural := (others => 0); 
   Num_Of_Digits : Natural; 
 
   type Sequence_item is record 
      Starts_At, Ends_At, Length : Natural; 
   end record; 
   Sequence: array(0..9) of Sequence_Item := (others=>(0,0,0)); 
   current_Digit, Current_Sequence_Length, Current_Sequence_Start: Natural :=0; 
 
   procedure Update_Sequence(Next_Digit_Position, next_digit: Natural) is 
   begin 
      if( next_Digit /= Current_Digit) then 
         if( Sequence( current_Digit ).Length < Current_Sequence_Length) then 
            Sequence( current_Digit ).Length := Current_Sequence_Length; 
            Sequence( current_Digit ).Starts_At := Current_Sequence_start; 
            Sequence( Current_Digit ).Ends_At := Next_Digit_Position -1; 
         end if; 
 
         Current_Digit := Next_Digit; 
         Current_Sequence_Length := 1; 
         Current_Sequence_Start  := Next_Digit_Position; 
 
      else 
         Current_Sequence_Length := Current_Sequence_Length +1; 
      end if; 
 
   end Update_Sequence; 
 
   procedure Done_Sequence( Current_Digit_Position: Natural)  is 
   begin 
      if( Sequence( current_Digit ).Length < Current_Sequence_Length) then 
         Sequence( current_Digit ).Length := Current_Sequence_Length; 
         Sequence( current_Digit ).Starts_At := Current_Sequence_start; 
         Sequence( Current_Digit ).Ends_At := current_Digit_Position ; 
      end if; 
   end Done_Sequence; 
 
begin 
 
   if( Argument_Count /= 1 ) then 
      Put_Line("usage: dist_e "); 
      return; 
   end if; 
 
   begin 
      Num_Of_Digits := natural'value( Argument(1)); 
 
      if( Num_Of_Digits = 0 ) then 
         Put_Line("value for number of digits must be larger than zero"); 
         return; 
      end if; 
 
   exception 
      when others => 
         Put_Line("Exception. invalid value for number of digits"); 
         return; 
   end; 
 
   declare            -- the algorithm itself is in this block 
      E: E_Type( 1 .. Num_Of_Digits+2 ) := (others=> 1); 
      Carry : Natural; 
   begin 
 
      Put("2."); 
 
      for I in E'first .. E'Last-2 loop 
         Carry := 0; 
         for J in reverse E'first .. E'Last loop 
            E(J) := ( E(J) * 10 ) + Carry; 
            Carry := E(J)/(J+1); 
            E(J) := E(J) rem (J+1); 
         end loop; 
 
         Put(Natural'Image(Carry)(2));            -- print current digit of e 
         Distribution( Carry ) := Distribution( Carry ) + 1; 
         Update_Sequence(I,Carry); 
      end loop; 
 
      Done_Sequence(E'Last-2); 
   end; 
 
   New_Line; 
   for I in Distribution'Range loop 
      Put_line("frequency of " & Natural'Image(I) & " is " 
               & natural'Image( Distribution(I)  )); 
   end loop; 
 
 
   for I in sequence'Range loop 
      if( Sequence(I).Length = 0 ) then 
         Put_Line("Digit "& Natural'Image(I) & " was not seen."); 
      else 
 
         Put_line("largest concecutive  seq of " & Natural'Image(I) 
                  &" started at digit " 
                  & natural'Image( sequence(I).Starts_at ) 
                  & " and ended at digit " 
                  & natural'Image( sequence(I).ends_at ) 
                  & " of length " 
                  & natural'Image( sequence(I).length )); 
      end if; 
   end loop; 
 
end Dist_E_final;