下面的这段代码显示:1 1.2 3
但是1 2.2 5.2
这是预料之中的。哪里错了?
\documentclass[tikz]{standalone}
\begin{document}
\xdef\Sum{0}
\foreach \i in {1,1.2,3} {
\pgfmathsetmacro\Sum{\Sum+\i}
\Sum\ }
\end{document}
答案1
看起来宏的定义\Sum
对于组来说是局部的。在下一次迭代中,它的内容会被遗忘,只有第一个全局定义会\xdef
被保留。不过我对此不太了解。
这是一个可行的示例(但可能不是最好的方法)。
\documentclass[tikz]{standalone}
\begin{document}
\xdef\Sum{0}
\foreach \i in {1,1.2,3} {
\xdef\Sum{\Sum+\i}
\pgfmathparse{\Sum}\pgfmathresult\ }
\end{document}
输出符合预期:1.0 2.2 5.2
答案2
和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}
答案3
这是一个可以准确打印所需数字总数的版本。
嗯...这不是所问的。抱歉。
好的,所以我更新了代码以打印所要求的部分和。正如已经指出的那样,问题\foreach
是限制范围的本地组之一。循环\xintFor
没有xinttools
这个问题。因此我在这里使用它。我在这里使用xintfrac
包的算法。但\xintFor
循环可以用作pgfmath
数学引擎。
然后,我之前关注的第二个元素是打印一个十进制数,其位数恰好是所需的位数。请注意,此处的宏与任意长的数字兼容。
代码:
\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}
答案4
只需练习渐近线使用内置sum(a)
函数计算给定实数数组所有元素的总和a
。
real[] a={1,1.2,-5};
write(a);
real T=sum(a);
write("The sum of all elements is");
write(T);