FPeval 在宏中

FPeval 在宏中

我正在写一份文档,其中需要大量使用以下结构

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

输出:

在此处输入图片描述

答案3

为了多样性,这里有一个基于 LuaLaTeX 的解决方案。

在此处输入图片描述

\documentclass{article}
\newcommand\lifespan[2]{%
    Born in #1, died in #2 (\directlua{tex.sprint(#2-#1)} years old).}

\begin{document}
\lifespan{1833}{1894}

\lifespan{1900}{1990}
\end{document}

相关内容