我正在写一份文档,其中需要大量使用以下结构
\FPeval{\born}{1833}
\FPeval{\died}{1894}
\FPeval{\age}{round(\died - \born,0)}
Born in \born, died in \died (\age years old)
我想写一个宏,这样我就可以编写\lifespan{1833}{1894}
并节省粘贴的时间。我试着写下显而易见的内容:
\newcommand{\lifespan}[2]{
\FPeval{\born}{#1}
\FPeval{\died}{#2}
\FPeval{\age}{round(\died - \born,0)}
Born in \born, died in \died (\age years old)
}
但它告诉我这\lifespan
是未定义的。有什么办法可以做到这一点,还是我只是在浪费时间?有什么办法可以编写宏 C 样式吗?有什么方法可以告诉 latex 在开始编译文档之前替换一些文本?
答案1
fp
对于整数的简单算术,没有必要使用这么大的枪:
\newcommand{\lifespan}[2]{%
Born in~#1, died in~#2 (%
{\count255=#2\relax
\advance\count255 by -#1\relax
\the\count255\relax}%
~years old)%
}
TeX 中的算术与 C 中的算术不同。
如果您喜欢不同的语法,请使用比更友好的工具fp
。
\documentclass{article}
\usepackage{xparse,xfp}
\NewDocumentCommand{\lifespan}{mm}{%
Born in~#1, died in~#2 (\inteval{#2-#1}~years old)%
}
\begin{document}
\lifespan{1879}{1955}
\end{document}
顺便说一句,您的代码运行完美(尽管您插入了几个不需要的空格和一个新段落)。
\documentclass{article}
\usepackage{fp}
\newcommand{\lifespan}[2]{
\FPeval{\born}{#1}
\FPeval{\died}{#2}
\FPeval{\age}{round(\died - \born,0)}
Born in \born, died in \died (\age years old)
}
\begin{document}
\lifespan{1833}{1894}
\end{document}
本文档编译时没有错误。
This is pdfTeX, Version 3.14159265-2.6-1.40.18 (TeX Live 2017) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./tst.tex
LaTeX2e <2017-04-15>
Babel <3.15> and hyphenation patterns for 84 language(s) loaded.
(/usr/local/texlive/2017/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/local/texlive/2017/texmf-dist/tex/latex/base/size10.clo))
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp.sty
`Fixed Point Package', Version 0.8, April 2, 1995 (C) Michael Mehlich
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/defpattern.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-basic.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-addons.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-snap.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-exp.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-trigo.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-pas.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-random.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-eqn.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-upn.sty)
(/usr/local/texlive/2017/texmf-dist/tex/latex/fp/fp-eval.sty))
No file tst.aux.
( FP-EVAL ( FP-UPN ) ) ( FP-EVAL ( FP-UPN ) ) ( FP-EVAL ( FP-UPN ( FP-SUB )
( FP-ROUND ) ) ) [1{/usr/local/texlive/2017/texmf-var/fonts/map/pdftex/updmap/p
dftex.map}] (./tst.aux) )</usr/local/texlive/2017/texmf-dist/fonts/type1/public
/amsfonts/cm/cmr10.pfb>
Output written on tst.pdf (1 page, 14096 bytes).
Transcript written on tst.log.
更好的版本是
\newcommand{\lifespan}[2]{%
\FPeval{\born}{#1}%
\FPeval{\died}{#2}%
\FPeval{\age}{round(\died - \born,0)}%
Born in \born, died in \died\ (\age\ years old)%
}
答案2
让我烦恼的是,你无法仅根据一个人出生和死亡的年份来判断他的年龄。你的计算可能会有一年的误差。所以,我建议你使用完整的日期并在此基础上进行计算。为了使用简单的\lifespan
语法,以下代码可能有点过于复杂。它首先解析日期,然后使用@egreg 的出色建议计算寿命xfp
:
\documentclass{article}
\usepackage{xparse,xfp,etoolbox}
\NewDocumentCommand{\splitdate}{mmmu{-}u{-}u{\relax}}{%
\def#1{#4}%
\def#2{#5}%
\def#3{#6}%
}
\NewDocumentCommand{\lifespan}{mm}{%
\splitdate\byear\bmonth\bday#1\relax
\splitdate\dyear\dmonth\dday#2\relax
\def\diff{0}%
\ifnumcomp{\bmonth}{>}{\dmonth}{%
\def\diff{1}%
}{%
\ifnumcomp{\bmonth}{=}{\dmonth}{%
\ifnumcomp{\bday}{>}{\dday}{%
\def\diff{1}%
}{}%
}{}}%
Born in~\byear, died in~\dyear\ (\inteval{\dyear-\byear-\diff}~years old)%
}
\begin{document}
\lifespan{1799-05-26}{1837-01-29}
\lifespan{1828-08-28}{1910-11-07}
\end{document}
输出: