9

How make LaTeX to remember some numbers and output the total sum by calling another command? Consider this example:

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

2 Answers 2

12

Here is a solution using the minifp package and some aux file magic (and so you need to run the file through latex twice to get the correct values).

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

enter image description here

Discussion

The command

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

defines the \pr macro, so that it first prints the input value (assumed to be a decimal number}, and adds it to the subtotal using the \MFPadd function of the minifp package. It then strips the trailing zeros using the \MFPstrip function. (Side note: minifp performs fixed-point arithmetic with up to 8 decimal places.)

The command \prsum just prints the subtotal; noticed that in the course of the text I've edited your file to use \prsum{} instead, to avoide the macro gobbling up the space afterwards. If you are only using \prsum in text, you can use xspace to circumvent this need.

To print the overall total sum, what we do is, at the end of the document (when you write \end{document}, write to the .aux file the current subtotal. We do this by writing it as a command definition: after running pdflatex on your file, the .aux file should contain the line

\gdef\student@allsum{14.86}

This line is read back into the stream around \begin{document} (when the aux file is read), and so overwrites the original definition of \student@allsum to be ???. We have to include an original definition because, before the first pass of pdflatex, the command \student@allsum would otherwise be undefined (since the aux file is generated during the run, and is not available to be read before the first run).

Notice that this means, like resolving label-references, that to update the correct value from \prallsum you need to run pdflatex at least twice after changing the file.

1
7

You can use xparse and expl3:

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

The macros should be sufficiently clear: \pr prints the given value and updates the total; at end document, the total is written in a suitable way in the aux file.

enter image description here

A warning might be added if the values of \g_student_sum_fp and \g_student_total_fp are different, telling the user that a new LaTeX run is needed: change the code from \AtEndDocument to \ExplSyntaxOff into

\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

In case the value has changed from the previous run, you get the warning

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

This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .