Truncation of Napier’s number (e) to an amount of decimal digits of my choice

Just for fun, here's an answer using LuaTeX that does the computation of the digits of e in Lua, without external data, and should be good for ~10000 digits at least. (Actually in principle the algorithm should work fine (just taking very long) for billions of digits or even millions of billions depending on how Lua is compiled, but you'll run out of patience and/or memory sooner.)

\documentclass{article}
\usepackage{luacode}
\begin{luacode}
-- Takes time ~n^2 to compute n digits. Tolerable until about n=10000.
function digits_e(n)
    -- Spigot algorithm by Rabinowitz and Wagon:
    -- http://www.cecm.sfu.ca/~jborwein/Expbook/Manuscript/Related%20files/spigot.pdf
    -- The idea: Just as we can say that
    -- e = 2 + (7, 1, 8, 2, 8, ...) in base (1/10, 1/10, 1/10, 1/10, 1/10, ...)
    -- the fact that e = sum(1/k!) over k≥0 gives, in the same notation,
    -- e = 2 + (1, 1, 1, 1, 1, ...) in base (1/2, 1/3, 1/4, 1/5, 1/6, 1/7, ...)
    -- We convert to the decimal base by repeatedly multiplying by 10.

    local len = n + 2
    -- After k≥0 steps, fractional part of (e-2)10^k in base (1/2, 1/3, 1/4, ...)
    local a = {}; for j = 1, len do a[j] = 1 end

    tex.sprint('2.')
    for k = 1, n do
        local carry = 0  -- We're about to multiply by 10, right to left.
        for i = len, 1, -1 do
            local x = carry + 10 * a[i]
            a[i] = math.fmod(x, i + 1)
            carry = math.modf(x / (i + 1))
        end
        tex.sprint(carry)
        if k % 1000 == 0 then print(string.format('Done %d digits', k)) end
        if k % 3 == 0 then tex.sprint([[\hskip 1.66663pt plus 0.6pt\relax]]) end
    end
end
\end{luacode}

\newcommand\napier[1]{\directlua{tex.sprint(digits_e(#1))}}

\begin{document}
\napier{2}

\napier{18}

\napier{100} % Last 10 digits: ...525 166 427 4

\napier{1000} % Last 10 digits: ...957 035 035 4

\napier{10000} % Last 10 digits: ...946 553 678 8
\end{document}

output

  • The algorithm I repurposed from what I had used earlier for pi, though it's quite a bit simpler for e.

  • It's O(n^2) so a bit slow (takes a few seconds for 10000 digits). We can speed it up by a small constant factor (like 10) by multiplying by a power of 10 instead of by 10 itself. (See block in the second revision of this answer; reverted to keep the code clear and simple.)

  • The algorithm is simple enough (and uses only arithmetic on small numbers, of roughly the size of the number of digits requested) that I suspect it could even be implemented with TeX macros and sufficiently many registers. :-)

  • I tried to use \num from siunitx but it was hard to figure out how to typeset a long number without overfull box warnings and the like -- it seems that the package does not provide such a feature and it looks complicated. Eventually gave up and wrote \hskip manually into the Lua code. :-)


I saved 100 decimal digits of e.

\documentclass{article}
\usepackage{siunitx} % also loads expl3 and xparse

\ExplSyntaxOn

\tl_const:Nn \c_sebastiano_napier_tl
 {
  71828182845904523536
  02874713526624977572
  47093699959574966967
  62772407663035354759
  45713821785251664274
 }

\NewDocumentCommand{\napier}{m}
 {
  \num{ 2.\tl_range:Nnn \c_sebastiano_napier_tl { 1 } { #1 } }
 }

\ExplSyntaxOff

\begin{document}

\napier{2}

\napier{18}

\end{document}

enter image description here

With possible line breaks use \napier*.

\documentclass{article}
\usepackage{amsmath}
\usepackage{siunitx} % also loads expl3 and xparse
\showthe\thinmuskip
\ExplSyntaxOn

\tl_const:Nn \c_sebastiano_napier_tl
 {
  71828182845904523536
  02874713526624977572
  47093699959574966967
  62772407663035354759
  45713821785251664274
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }

\NewDocumentCommand{\napier}{sm}
 {
  \IfBooleanTF { #1 }
   {
    \sebastiano_napier_inline:n { #2 }
   }
   {
    \num{ 2.\tl_range:Nnn \c_sebastiano_napier_tl { 1 } { #2 } }
   }
 }

\cs_new_protected:Nn \sebastiano_napier_inline:n
 {
  \seq_set_split:Nnx \l_tmpa_seq {} { \tl_range:Nnn \c_sebastiano_napier_tl { 1 } { #1 } }
  2.\seq_indexed_map_function:NN \l_tmpa_seq \__sebastiano_napier_split:nn
 }

\cs_new_protected:Nn \__sebastiano_napier_split:nn
 {
  #2
  \int_compare:nT { \int_mod:nn { #1 } { 3 } = 0 }
   {
    \mode_if_math:TF
     {
      \penalty \c_zero_int
      \mspace{1\thinmuskip plus 1\thinmuskip}
     }
     {
      \hspace{0.16667em plus 0.16667em}
     }
   }
 }

\ExplSyntaxOff

\begin{document}

\napier{2}

\napier{18}

\napier*{99}

$\napier*{99}$

\end{document}

enter image description here


Here's a LuaLaTeX-based solution. It provides two LaTeX utility macros -- \ShowNum and \ShowGrNum -- as well as two Lua functions that perform the actual work.

Some comments:

  • Because Lua performs "just" double-precision calculations, you should not use this approach if you intend to show more than about 15 decimal digits. If you do intend to show more than 15 decimal digits, it's necessary to either pre-store the numbers of interest up to some desired level of precision, as is shown in @egreg's answer as well as in the addendum shown below, or to pursue an arbitrary-precision approach such as the one pursued in @ShreevatsaR's answer.

  • The LaTeX macro \ShowNum takes 2 arguments: The number itself, and the number of decimal digits to be shown. No grouping is performed.

    • The first argument of \ShowNum can be a constant, e.g., 12345.6789012, or something that can be evaluated meaningfully by Lua, e.g., math.exp(1), math.pi, 2*math.acos(0), or 2*math.asin(1).

    • The four arithmetic symbols +-*/ are ok in the first argument; however, don't use ^ (exponentiation) in the first argument of \ShowNum as LaTeX will interpret it as the start of superscript material. In general, be careful lest the first argument contain material that could get expanded by LaTeX in some unanticipated manner.

    • Of course, it's fine for the first argument of \ShowNum to contain LaTeX macros that expand to something that can be handled by Lua.

  • The macro \ShowGrNum takes the same 2 arguments as \ShowNum, plus an optional argument that determines the type of grouping. The optional argument should be an integer (aka a positive whole number). The default value of the optional argument is 3, i.e., the decimal part (but not the integer part) will be grouped in chunks of 3 digits by default. Note that \ShowGrNum allows line breaking after each group of numbers; this is in contrast to the properties of the \num macro of the siunitx package.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function PrintNum ( n , m )
   -- n: number to be printed
   -- m: number of decimal digits to be shown
   return string.format ( "%."..m.."f" , n ) 
end   

function GroupNum ( s , g )
   -- s: number whose decimal part should be grouped
   -- g: number of digits in group (say, '3')
   s = tostring ( s )
   local m 
   m = s:find ( "%." ) -- find the integer part of 's'
   if m then -- print integer part first
     tex.sprint ( s:sub(1,m) ) -- no grouping applied
     s = s:sub(m+1)
   end
   -- Apply visual grouping to decimal part:
   while #s > g do
      tex.sprint ( s:sub(1,g) .. "\\hspace{0.1666em}\\allowbreak")
      s = s:sub(g+1) -- discard the first 'n' chars
   end
   tex.sprint ( s )
end   
\end{luacode}
%% Define 2 LaTeX macros:
%%   \ShowNum just prints the number
%%   \ShowGrNum additionally groups the number
\newcommand\ShowNum[2]{\directlua{%
   tex.sprint ( PrintNum ( #1 , #2 ) )}}
\newcommand\ShowGrNum[3][3]{\directlua{%
   GroupNum ( PrintNum ( #2 , #3 ) , #1 )}}

\begin{document}
\ShowNum{math.exp(1)}{15}

$\ShowNum{math.pi}{15}$

\smallskip
\ShowGrNum{math.exp(1)}{15}

$\ShowGrNum[4]{2*math.acos(0)}{15}$
\end{document}

Addendum: Just for fun, here's a version of the LuaLaTeX solution that stores the first 2000 decimal digits of Napier's number. Anywhere from 0 to 2000 digits can be shown via the LaTeX macro \Napier. The macro takes an optional argument: the number of digits in each group. (The default grouping number is 3.) As in the answer above, the grouping is performed with the help of Lua's powerful string.sub function.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
-- store the first 2000 decimal digits of Napier's number as a string:
local napiernum = "71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770417189861068739696552126715468895703503540212340784981933432106817012100562788023519303322474501585390473041995777709350366041699732972508868769664035557071622684471625607988265178713419512466520103059212366771943252786753985589448969709640975459185695638023637016211204774272283648961342251644507818244235294863637214174023889344124796357437026375529444833799801612549227850925778256209262264832627793338656648162772516401910590049164499828931505660472580277863186415519565324425869829469593080191529872117255634754639644791014590409058629849679128740687050489585867174798546677575732056812884592054133405392200011378630094556068816674001698420558040336379537645203040243225661352783695117788386387443966253224985065499588623428189970773327617178392803494650143455889707194258639877275471096295374152111513683506275260232648472870392076431005958411661205452970302364725492966693811513732275364509888903136020572481765851180630364428123149655070475102544650117272115551948668508003685322818315219600373562527944951582841882947876108526398139"

function Napier ( n , g )
  -- n: number of decimal digits to be shown (0\le n \le 2000) 
  -- g: number of digits per group (3 by default)
  if n==0 then -- no decimal part to show
    tex.sprint ( "2" ) 
  else
    e = napiernum:sub ( 1 , n ) -- retain the first n digits
    tex.sprint "2."
    while #e>g do
      tex.sprint ( e:sub ( 1 , g ) .. "\\,\\allowbreak" )
      e = e:sub ( g+1 ) -- discard first g digits
    end
    tex.sprint ( e ) -- display remaining digits (if any)
  end
end
\end{luacode}
%% LaTeX macro to show first n digits of "e", grouped:
\newcommand\Napier[2][3]{\directlua{Napier(#2,#1)}}

\begin{document}
\raggedright
\Napier{0}, \Napier{1}, \Napier{9}

\smallskip
\Napier[8]{1024} % in groups of 8
\end{document}