2

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}
1
  • 5
    The body of a \foreach statement is carried out in a new group. See the pgf manual for more information. – user10274 May 21 '14 at 13:29
4

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

1
  • 1
    '\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). – user10274 May 21 '14 at 14:27
5

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_add:Nn \l__tarass_partial_sum_fp { ##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}

enter image description here

2

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.

partial sums

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
       {\oodef\Sum{\xintAdd{\Sum}{##1}}%
        \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
       {\oodef\Sum{\xintAdd{\Sum}{##1}}%
        \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}

sum list of decimal numbers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.