# Summation of a list of numbers

The next code gives : 1 1.2 3 But 1 2.2 5.2 is expected. What is wrong ?

\documentclass[tikz]{standalone}

\begin{document}

\xdef\Sum{0}
\foreach \i in {1,1.2,3} {
\pgfmathsetmacro\Sum{\Sum+\i}
\Sum\ }

\end{document}

-
The body of a \foreach statement is carried out in a new group. See the pgf manual for more information. –  Marc van Dongen May 21 at 13:29

It seems like the definition of the macro \Sum is local to the group. At the next iteration, its content is forgotten and only the first global definition with \xdef is kept. I don't know much about it though.

Here is a working example (but probably not the best way to do it).

\documentclass[tikz]{standalone}

\begin{document}

\xdef\Sum{0}
\foreach \i in {1,1.2,3} {
\xdef\Sum{\Sum+\i}
\pgfmathparse{\Sum}\pgfmathresult\ }

\end{document}


The output is as expected: 1.0 2.2 5.2

-
'\xdef\ is equivalent to '\global\edef', so it expands the second argument (the substitution text) once and globally binds it to the first argument (the command sequence). –  Marc van Dongen May 21 at 14:27

With expl3:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand\sumlist{ m }
{
\tarass_sum_list:n { #1 }
}

\fp_new:N \l__tarass_partial_sum_fp

\cs_new_protected:Npn \tarass_sum_list:n #1
{
\fp_zero:N \l__tarass_partial_sum_fp
\clist_map_inline:nn { #1 }
{
$\fp_use:N \l__tarass_partial_sum_fp$
\ %
}
\unskip % remove the last space
}
\ExplSyntaxOff

\begin{document}

\sumlist{1,1.2,3}

\sumlist{1,-1.2,3}

\end{document}


-

Here is a version which will print the sum exactly with the number of necessary digits.

Hmm... that was not what was asked.Sorry.

Ok, so I update the code to do the printing of partial sums which was asked for. As has been pointed out the issue with \foreach is one of local groups limiting the scope. The \xintFor loop from xinttools does not have this issue. And thus I use it here. While I am at it I use the arithmetics of xintfrac package. But the \xintFor loop could have been used with pgfmath as math engine.

Then, the second element which I earlier had focused on is the printing of a decimal number with exactly the number of digits needed. Notice that the macros here are compatible with arbitrarily long numbers.

Code:

\documentclass{article}

\usepackage{xintfrac}
\usepackage{xinttools}

% Let's first do the partial sums as fixed point numbers.
% We hardcode \Sum macro to hold the partial sums
\newcommand\TarassSumList [1]{\def\Sum{0}\xintFor ##1 in {#1}\do
\xintRound{4}{\Sum}%
\xintifForLast{}{, }}}

% let's now do it again but printing with the number of necessary
% digits:

%
% We abstract some command from code below (an expandable version
% should be added to xint package)

\makeatletter
\def\ReduceDec@helper #1[#2]{#2}% duplicate of \sumlist@helper
\newcommand\ReduceDec [1]{%
\oodef\ReduceDec@X {\xintREZ{#1}}%
\oodef\ReduceDec@N {\expandafter\ReduceDec@helper\ReduceDec@X }%
\ifnum\ReduceDec@N<\z@
\oodef\ReduceDecResult{\xintTrunc {-\ReduceDec@N}{\ReduceDec@X}}%
\else
\oodef\ReduceDecResult{\xintNum \ReduceDec@X}%
\fi }
\makeatother

\newcommand\TarassSumListB [1]{\def\Sum{0}\xintFor ##1 in {#1}\do
\ReduceDec{\Sum}\let\Sum\ReduceDecResult
\Sum
\xintifForLast{}{, }}}

% earlier answer which concentrated on the printing of decimal number with
% exactly the needed number of digits.

% sum decimal numbers, and print the result with exactly as
% many digits as necessary after the decimal mark

% It would be  quite easier to print a truncation or rounding to a
% given number of digits after decimal mark (\xintTrunc or \xintRound
% and the whole thing would be completely expandable)

% To avoid scaring people, I did not make this more challenging version
% expandable...

% And it is to be used only for decimal numbers or scientific number on
% input, no fractions like 3/7.

\makeatletter
\def\sumlist@helper #1[#2]{#2}% there should be a macro in xintfrac for that
\newcommand\sumlist [1]{%
\oodef\sumlist@S {\xintREZ{\xintSum{\xintCSVtoList {#1}}}}%
\oodef\sumlist@N {\expandafter\sumlist@helper\sumlist@S }%
\ifnum\sumlist@N<\z@
\xintTrunc {-\sumlist@N}{\sumlist@S}%
\else
\xintNum \sumlist@S
\fi}
\makeatother

\begin{document}\thispagestyle{empty}

Fixed point numbers (4 decimal digits):

\TarassSumList{1,1.2,3}

\TarassSumList{1,-1.2,3}

\TarassSumList {1.23, 3.31, -0.54}

\TarassSumList {1.234, 5.6789, 3.211768, -17.28929}

\TarassSumList {1.234, 5.6789, 3.211768, -17.28929, 13.004622}

\TarassSumList {1.23e-3, 3.25e-3, 17.123e-4}

Numbers with as many digits as necessary:

\TarassSumListB{1,1.2,3}

\TarassSumListB{1,-1.2,3}

\TarassSumListB {1.23, 3.31, -0.54}

\TarassSumListB {1.234, 5.6789, 3.211768, -17.28929}

\TarassSumListB {1.234, 5.6789, 3.211768, -17.28929, 13.004622}

\TarassSumListB {1.23e-3, 3.25e-3, 17.123e-4}

% \sumlist{1,1.2,3}

% \sumlist{1,-1.2,3}

% \sumlist {1.23, 3.31, -0.54}

% \sumlist {1.234, 5.6789, 3.211768, -17.28929}

% \sumlist {1.234, 5.6789, 3.211768, -17.28929, 13.004622}

% \sumlist {1.23e-3, 3.25e-3, 17.123e-4}

% \sumlist {100, 200}

\end{document}


-