如何在纯 TeX 中进行加、减、乘、除运算?

如何在纯 TeX 中进行加、减、乘、除运算?

我发现很多情况下我需要使用加、减、乘、除来计算许多数字,但如果 TeX 可以简单地为我计算这些,那将节省大量时间。

这是一个示例情况,可以计算出在课堂上花费了多少分钟或多少小时,以及其中有多少分钟是在实验室里花费的。

\def\weeks{20} % term is twenty weeks
\def\lessonsperweek{3} % meets three times per week
\def\lessonduration{60} % meets for sixty minutes

\def\percentlectures{.5} % half the time is spent in lectures
\def\percentdiscussions{.2} % 20 percent of the time is spent in disucssions
\def\percentlab{1 - \percentdiscussions - \percentlectures} % remaining percent of time left to lab work

\def\totalduration{\lessonduration * \lessonsperweek * \weeks} % minutes spent in lessons

\def\totaldurationhours{\totalduration / 60}

\def\labduration{\totalduration * \percentlabs} % minutes spent in the lab

Total time in lab: \labduration minutes.

Total minutes in class: \totalduration minutes.

Total hours in class: \totaldurationhours hours.

\def\weeks{19} % these two values are changed later in the document
\def\lessonsperweek{2}

Total minutes in class: \totalduration minutes. % this value would be different because of the chagnes to \weeks and \lessonsperweek

当我编译这个时,+-*/只是在文档中显示为符号。我该如何让 TeX 计算这些值?

答案1

您可以使用表达式进行算术运算(使用,,,,,+但不能计算幂 )。-*/^\numexpr

这些\numexpr表达式是e-TeXKnuth 的扩展之一TeX

(e-TeX 扩展:在现代安装中,它们默认被激活,除非您使用tex命令行中命名的可执行文件)

但是您不能在里面使用真正的小数\numexpr...\relax(例如执行1/7+1/3)。 并且/在其中执行(四舍五入)除法到最接近的整数。 整数必须介于 和 之间-2147483647+2147483647这与可以存储在 TeX\count或 LaTeX 中的整数的限制相同counter; 并且\count可以直接在表达式中使用\numexpr,对于 LaTeXcounter\value{mycountername}

我写了包xintexpr可以在 Plain TeX ( \input xintexpr.sty) 或 LaTeX ( \usepackage{xintexpr}) 中使用。

  1. 如果您希望将最终结果四舍五入为整数,请使用\xintiexpr,例如\xintiexpr 123456789987654321/(2^32+3^20)\relax。否则\xintexpr将计算分数。

  2. 如果想要不可约形式的分数,请使用函数reduce\xintexpr reduce (1/1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+1/9+1/10)\relax

  3. 相反,\numexpr在 TeX 需要整数的地方可以直接使用 ,例如在测试中\ifnum,需要在: (或)\xintiexpr前面加上前缀。但自然,生成的数字应该小于限制。\xintthe\xintthe\xintiexpr\xinttheiexpr2^31

  4. 测试中不能使用an \xintthe\xintexpr(或更短的) ,因为 TeX 不理解分数。该包提供了自己的测试来比较数字(包括分数)。\xinttheexpr\ifnum

  5. 表达式\xintexpr必须以 终止,\relax而 a\numexpr将合法地以任何不符合其语法要求的标记(如点.)终止。

  6. \numexpr -(1+2)\relax不起作用!但是\xintexpr -(1+2)\relax……

  7. \xintexpr是完全可扩展的。

因此,诸如此类的事情:

\message{\xinttheexpr reduce (1/1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+1/9+1/10)\relax}
\message {\xinttheiexpr 123456789987654321/(2^32+3^20)\relax}

是可能的。

OP 用例的代码:

\input xintexpr.sty\relax % compile with etex or pdftex

% macro to use \xinttheiexpr which will round to the nearest whole number.
\def\roundandprint #1{\xinttheiexpr #1\relax }

\def\weeks{20}          % term is twenty weeks
\def\lessonsperweek{3}  % meets three times per week
\def\lessonduration{60} % meets for sixty minutes

\def\percentlectures{.5}    % half the time is spent in lectures
\def\percentdiscussions{.2} % 20 percent of the time is spent in disucssions

% remaining percent of time left to lab work:
\def\percentlab{\xintexpr 1 - \percentdiscussions - \percentlectures\relax} 

% minutes spent in lessons:
\def\totalduration{\xintexpr \lessonduration * \lessonsperweek * \weeks\relax} 

% total duration in hours:
\def\totaldurationhours{\xintexpr \totalduration / 60 \relax}

% minutes spent in the lab:
\def\labduration{\xintexpr \totalduration * \percentlab \relax} 

Total time in lab: \roundandprint{\labduration} minutes.

Total minutes in class: \roundandprint{\totalduration} minutes.

Total hours in class: \roundandprint{\totaldurationhours} hours.

\def\weeks{19} % these two values are changed later in the document
\def\lessonsperweek{2}

Total minutes in class: \roundandprint{\totalduration} minutes. % this value
                                % would be different because of the chagnes to
                                % \weeks and \lessonsperweek

\bye

加减乘除

\xintexpr ... \relax备注:等中的各种表达式\percentlab都是可选的;它们可以用括号代替,但使用这样的\xintexpr ... \relax子表达式可以提供最大的灵活性。例如,\edef如果计算中涉及的所有内容都在当时定义,那么可以将它们嵌入到中。

如前例所述,^幂的 是可以接受的:但指数必须是整数(3^(10/2)是可以的\xintexpr,这样可以正确计算3^5)。有一个sqrt函数可以计算平方根,默认情况下16精度为 位数。第二个可选参数允许更高的精度:

\xinttheexpr sqrt(2,60)\relax

给出60精度位数。要以科学计数法得到结果,则:

\xintthefloatexpr sqrt(2,60)\relax

答案2

纯文本 tex(唯一)通常与经典 Tex 引擎一起使用(或至少禁用 pdf 和 e-tex 扩展),因此没有中缀算法

\newcount\zzz
\zzz=5
\multiply\zzz by 3
\advance\zzz by 2

设置\zzz为 17。如果您使用 e-tex 的纯格式,则可以使用 e-tex 中缀算术

\newcount\zzz
\zzz=\numexpr 5*5 + 2\relax

答案3

您可以使用 PGFmath。

对于\pgfmathprintnumberfrom ( pgfmathfloat.code.tex) ,需要定义\pgf@texdist@protect,原因我不清楚(这似乎是某种保护机制)。
简单来说, \inputtingpgf.tex也可以。

代码

\expandafter\def\csname pgf@texdist@protect\endcsname{}%
\input pgfmath.tex
\def\weeks{20}          % term is twenty weeks
\def\lessonsperweek{3}  % meets three times per week
\def\lessonduration{60} % meets for sixty minutes

\def\percentlectures{.5}    % half the time is spent in lectures
\def\percentdiscussions{.2} % 20 percent of the time is spent in disucssions
                            % remaining percent of time left to lab work
\def\percentlab{1 - \percentdiscussions - \percentlectures}
                            % minutes spent in lessons
\def\totalduration{\lessonduration * \lessonsperweek * \weeks}
\def\totaldurationhours{(\totalduration) / 60}
\def\labduration{(\totalduration) * (\percentlab)} % minutes spent in the lab

\pgfset{
  number format/.cd,
  min exponent for 1000 sep=4,
  int detect,
}
Total time in lab: \pgfmathprint{\labduration} (\pgfmathprintnumber[fixed,precision=0]{\pgfmathresult}) minutes.

Total minutes in class: \pgfmathprint{\totalduration}
                 (\pgfmathprintnumber{\pgfmathresult}) minutes.

Total hours in class: \pgfmathprint{\totaldurationhours} 
               (\pgfmathprintnumber{\pgfmathresult}) hours.

\def\weeks{19}         % these two values are changed later in the document
\def\lessonsperweek{2}
                       % minutes spent in lessons

% this value would be different because of the chagnes to \weeks and \lessonsperweek
Total minutes in class: \pgfmathprint{\totalduration}
                 (\pgfmathprintnumber{\pgfmathresult}) minutes.
\bye

输出

在此处输入图片描述

答案4

如果要从计数器中减去,请使用负值:

\newcount\h
\h 12
\advance\h -1

相关内容