我发现很多情况下我需要使用加、减、乘、除来计算许多数字,但如果 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-TeX
Knuth 的扩展之一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}
) 中使用。
如果您希望将最终结果四舍五入为整数,请使用
\xintiexpr
,例如\xintiexpr 123456789987654321/(2^32+3^20)\relax
。否则\xintexpr
将计算分数。如果想要不可约形式的分数,请使用函数
reduce
:\xintexpr reduce (1/1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+1/9+1/10)\relax
。相反,
\numexpr
在 TeX 需要整数的地方可以直接使用 ,例如在测试中\ifnum
,需要在: (或)\xintiexpr
前面加上前缀。但自然,生成的数字应该小于限制。\xintthe
\xintthe\xintiexpr
\xinttheiexpr
2^31
测试中不能使用an
\xintthe\xintexpr
(或更短的) ,因为 TeX 不理解分数。该包提供了自己的测试来比较数字(包括分数)。\xinttheexpr
\ifnum
表达式
\xintexpr
必须以 终止,\relax
而 a\numexpr
将合法地以任何不符合其语法要求的标记(如点.
)终止。\numexpr -(1+2)\relax
不起作用!但是\xintexpr -(1+2)\relax
……\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。
对于\pgfmathprintnumber
from ( pgfmathfloat.code.tex
) ,需要定义\pgf@texdist@protect
,原因我不清楚(这似乎是某种保护机制)。
简单来说, \input
tingpgf.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