如何添加文本中出现的数字?

如何添加文本中出现的数字?

如何让 LaTeX 记住一些数字并通过调用另一个命令输出总和?考虑这个例子:

\documentclass{article}

\usepackage{lipsum}

\begin{document}

The price of the first item is \pr{10.23}, that of the second item is 

\pr{2.30}. 

%% The command \pr{10.23} should print the number 10.23 (perhaps with unit) and then remember it for the total sum.    

The total so far  is \prsum the overall total sum is \prallsum.
%% should print 12.53 and 14.86.
There is another item about \pr{2.33}. 

Not the total sum so far is \prsum and the overall total sum is \prallsum

%% This should print 14.86 in both cases.


\end{document}

答案1

这是一个使用的解决方案minifp包和一些aux文件魔法(因此您需要运行文件latex两次才能获得正确的值)。

\documentclass{article}
\usepackage{minifp}

\makeatletter
\newcommand*\@subtotal{0}
\newcommand*\pr[1]{%
    #1%
    \MFPadd{\@subtotal}{#1}\@subtotal\relax%
    \MFPstrip{\@subtotal}\@subtotal}
\newcommand*\prsum{\@subtotal}
\def\student@allsum{???}
\gdef\prallsum{\student@allsum}

\AtEndDocument{%
    \write\@auxout{\string\gdef\string\student@allsum{\@subtotal}}}
\makeatother

\begin{document}
The price of the first item is \pr{10.23}, that of the second item is 

\pr{2.30}. 


The total so far  is \prsum{} the overall total sum is \prallsum.
There is another item about \pr{2.33}. 

Not the total sum so far is \prsum{} and the overall total sum is \prallsum.
\end{document}

在此处输入图片描述

讨论

命令

\newcommand*\pr[1]{%
    #1%
    \MFPadd{\@subtotal}{#1}\@subtotal\relax%
    \MFPstrip{\@subtotal}\@subtotal}

定义\pr宏,以便它首先打印输入值(假定为十进制数),然后使用包\MFPadd的函数将其添加到小计中minifp。然后使用该函数删除尾随的零\MFPstrip。(旁注:minifp执行最多 8 位小数的定点运算。)

该命令\prsum仅打印小计;注意到在文本过程中,我已编辑了您的文件以改用\prsum{},以避免宏随后吞噬空间。如果您仅\prsum在文本中使用,则可以使用xspace以避免这种需要。

要打印总和,我们要做的是,在文档末尾(当您写入时,将当前小计\end{document}写入文件。我们通过将其写为命令定义来实现这一点:在文件上运行后,该文件应包含以下行.auxpdflatex.aux

\gdef\student@allsum{14.86}

这一行在 左右被读回到流中\begin{document}(当aux读取文件时),因此将 的原始定义覆盖\student@allsum???。我们必须包含原始定义,因为在 的第一次传递之前pdflatex,命令\student@allsum将未定义(因为aux文件是在运行期间生成的,并且在第一次运行之前无法读取)。

请注意,这意味着,就像解析标签引用一样,要更新正确的值,您至少\prallsum需要运行pdflatex两次更改文件后。

答案2

您可以使用xparseexpl3

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\fp_new:N \g_student_sum_fp
\fp_new:N \g_student_total_fp

\NewDocumentCommand{\pr}{m}
 {
  \fp_eval:n { #1 } % print the value
  \fp_gadd:Nn \g_student_sum_fp { #1 } % add to the global container
 }
\DeclareExpandableDocumentCommand{\prsum}{}
 {
  \fp_eval:n { \g_student_sum_fp }
 }
\DeclareExpandableDocumentCommand{\prallsum}{}
 {
  \fp_eval:n { \g_student_total_fp }
 }

\AtEndDocument
 {
  \iow_now:cx { @auxout }
   {
    \ExplSyntaxOn ^^J
    \fp_gset:Nn \exp_not:N \g_student_total_fp { \fp_eval:n { \g_student_sum_fp } } ^^J
    \ExplSyntaxOff ^^J
   }
 }

\ExplSyntaxOff

\begin{document}

The price of the first item is \pr{10.23}, that of the second item is 
\pr{2.30}. 

The total so far is \prsum{} and the overall total sum is \prallsum.

There is another item about \pr{2.33}. 

Now the total sum so far is \prsum{} and the overall total sum is \prallsum.


\end{document}

宏应该足够清晰:\pr打印给定的值并更新总数;在文档结束时,总数以适当的方式写在辅助文件中。

在此处输入图片描述

\g_student_sum_fp如果和的值不同,则可能会添加警告\g_student_total_fp,告诉用户需要重新运行 LaTeX:将代码从更改\AtEndDocument\ExplSyntaxOff

\AtEndDocument
 {
  \iow_now:cx { @auxout }
   {
    \ExplSyntaxOn ^^J
    \fp_gset:Nn \exp_not:N \g_student_total_fp { \fp_eval:n { \g_student_sum_fp } } ^^J
    \ExplSyntaxOff ^^J
   }
  \fp_compare:nF { \g_student_sum_fp = \g_student_total_fp }
   {
    \msg_warning:nn { student/sum } { rerun }
   }
 }

\msg_new:nnn { student/sum } { rerun }
 {
  Value~for~\exp_not:N \prallsum has~changed.~Rerun~LaTeX
 }

\ExplSyntaxOff

如果值与上次运行相比发生了变化,则会收到警告

*************************************************
* student/sum warning: "rerun"
* 
* Value for \prallsum has changed. Rerun LaTeX
*************************************************

相关内容