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}
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
fromsiunitx
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}
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}
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)
, or2*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 is3
, 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 thesiunitx
package.
% !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.
% !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}