将纳皮尔数 (e) 截断为我选择的十进制数字

将纳皮尔数 (e) 截断为我选择的十进制数字

当我写出超越纳皮尔数的十进制数字时,我的学生总是很高兴。我只记得 30 位十进制数字,例如。我提醒所有读者,我不是这个siunitx包的专家。但是,我知道正确处理其中的数字、单位和空格很重要。:-)

在此处输入图片描述

\documentclass{article}
\begin{document}
$e=2.718281828459045235360287471352\dots$
\end{document}

使用此小部件沃尔夫拉姆阿尔法纳皮尔数我可以选择小数位数。 是否可以使用 LaTeX 实现同样的功能?

答案1

我保存了 100 位小数

\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}

在此处输入图片描述

尽可能使用换行符\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}

在此处输入图片描述

答案2

只是为了好玩,这里有一个使用 LuaTeX 的答案,它可以计算 Lua 中的数字e,无需外部数据,至少可以计算约 10000 位数字。 (实际上,原则上,该算法应该可以很好地工作 (只是需要很长时间),适用于数十亿位数字甚至数百万亿位数字,具体取决于 Lua 的编译方式,但您很快就会失去耐心和/或内存。)

\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}

输出

  • 我重新利用了以前使用的算法早期的 pi,尽管对于 e 来说它要简单得多。

  • 它的复杂度为 O(n^2),因此有点慢(10000 位数字需要几秒钟)。我们可以通过乘以 10 的幂而不是乘以 10 本身来将其速度提高一个小的常数倍(例如 10)。(block参见此答案的第二次修订;恢复以保持代码清晰和简单。)

  • 该算法足够简单(并且仅使用小数字的算术,其大小大致与请求的数字相同),我怀疑它甚至可以用 TeX 宏和足够多的寄存器来实现。:-)

  • 我尝试使用\numfrom siunitx,但很难弄清楚如何排版长数字而不会出现框满警告等问题——似乎该包不提供这样的功能,而且它看起来很复杂。最终还是放弃了,\hskip手动写入 Lua 代码。:-)

答案3

这是一个基于 LuaLaTeX 的解决方案。它提供了两个 LaTeX 实用宏 --\ShowNum\ShowGrNum-- 以及两个执行实际工作的 Lua 函数。

一些评论:

  • 因为 Lua 只执行双精度计算,所以你应该不是如果您打算显示超过 15 位十进制数字,请使用此方法。如果您确实打算显示超过 15 位十进制数字,则需要预先存储感兴趣的数字,直到达到所需的精度水平,如@egreg 的回答以及下面所示的附录,或者追求任意精度的方法,比如@ShreevatsaR 的回答

  • LaTeX 宏\ShowNum接受 2 个参数:数字本身和要显示的小数位数。不进行分组。

    • 的第一个参数可以是\ShowNum常量,例如,,12345.6789012或者是可以由Lua 进行有意义评估的内容,例如math.exp(1),,,,或。math.pi2*math.acos(0)2*math.asin(1)

    • 第一个参数中可以使用四个算术符号+-*/;但是,不要^在第一个参数中使用(指数),\ShowNum因为 LaTeX 会将其解释为上标材料的开始。一般来说,要小心,以免第一个参数包含可能被 LaTeX 以某种意想不到的方式扩展的材料。

    • 当然,第一个参数\ShowNum包含扩展为 Lua 可以处理的内容的 LaTeX 宏是可以的。

  • 该宏\ShowGrNum采用与 相同的 2 个参数\ShowNum,外加一个确定分组类型的可选参数。可选参数应为整数(又称正整数)。可选参数的默认值为3,即小数部分(但不是整数部分)将默认以 3 位数字的块分组。请注意,允许在每组数字后换行;这与包的宏\ShowGrNum的属性相反。\numsiunitx

在此处输入图片描述

% !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}

附录:只是为了好玩,这里有一个 LuaLaTeX 解决方案版本,它存储了纳皮尔数的前 2000 位十进制数字。通过 LaTeX 宏可以显示从 0 到 2000 的任何数字\Napier。该宏有一个可选参数:每组中的数字位数。(默认分组数为 3。)如上面的答案所示,分组是借助 Lua 强大的功能进行的string.sub

在此处输入图片描述

% !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}

答案4

答案sagetex可以稍微缩短一点,改编一下 PeterGrill 的回答格式化小数。使用numprint包和 minipage 环境可防止 SAGE 输出溢出行。由于这对于较长的 SAGE 输出很有用,因此我在下面添加了代码。

\documentclass[]{article}
\usepackage{sagetex,numprint}
\npdecimalsign{\ensuremath{.}}%
\npthousandsep{ }%
\begin{document}
\begin{sagesilent}
output = r"\begin{minipage}{.95\linewidth}"
output += r"\numprint{%s}"%(e.n(digits=1000))
output += r"\end{minipage}"
\end{sagesilent}
$\sagestr{output}$
\end{document}

Cocalc 中的运行输出如下:

在此处输入图片描述

相关内容