
Кажется, что нельзя добавить \global
перед a, \pgfmathsetmacro
так как это дает:
Префикс с `\begingroup' использовать нельзя.
Но именно эта функциональность мне здесь и нужна.
Я пытаюсь вычислить среднее значение целых чисел в списке. В MWE список у меня такой:
\newcommand*{\MyData}{3,7,X,Y,8,9,Z}%
и \typeout
сообщения показывают:
**** NumberOfValidEnteries=1, \AverageValue=3.0
**** NumberOfValidEnteries=2, \AverageValue=3.5
**** NumberOfValidEnteries=3, \AverageValue=2.66666
**** NumberOfValidEnteries=4, \AverageValue=2.25
Таким образом, похоже, что \pgfmathsetmacro
работает, за исключением того, что он не сохраняет свое состояние между последовательными итерациями \foreach
, а именно \global
для этого изначально и был предназначен .
Код:
\documentclass{article}
\usepackage{tikz}
\usepackage{xstring}
% http://tex.stackexchange.com/questions/50111/how-to-check-if-the-value-of-a-parameter-is-a-number
\newcommand*{\IfIsInteger}[3]{%
\IfStrEq{#1}{ }{%
#3% is a blank string
}{%
\IfInteger{#1}{#2}{#3}%
}%
}%
\newcommand*{\MyData}{3,7,X,Y,8,9,Z}%
\newcommand*{\AverageValue}{0}
\newcounter{NumberOfValidEnteries}
\newcommand*{\ComputeAverage}[1]{%
%% Initialize (in case this is used more than once)
\renewcommand*{\AverageValue}{0}
\setcounter{NumberOfValidEnteries}{0}%
%
\edef\ExpandedDataEnteries{#1}% So that #1 can be a list or a macro defined list.
\foreach \NewData in \ExpandedDataEnteries {%
\IfIsInteger{\NewData}{%
%\global% <---- I need this ????
\pgfmathsetmacro{\AverageValue}{%
(\AverageValue * \arabic{NumberOfValidEnteries} + \NewData) /
(\arabic{NumberOfValidEnteries} + 1)
}%
\stepcounter{NumberOfValidEnteries}%
\typeout{**** NumberOfValidEnteries=\arabic{NumberOfValidEnteries}, \string\AverageValue=\AverageValue}%
}{%
% Not integer data so skip it
}%
}%
}
\begin{document}
\ComputeAverage{\MyData}%
Average of integers in ``\MyData" is ``\AverageValue".
\end{document}
решение1
Вы можете по закону разместить \global
только перед командой присваивания:
\global\def
\global\let
\global\mathchardef
\global\catcode
\global\advance
и т. д. Следует отметить, что\global
хочет и ищетподходящая команда, следующая за ней, выполняющая расширение. Например, etoolbox
определяет
\newrobustcmd{\cslet}[2]{%
\expandafter\let\csname#1\endcsname#2}
так что \global\cslet{foo}{\bar}
это законно, потому что это станет
\global\expandafter\let\csname foo\endcsname\bar
после первого расширения, но так как \expandafter
является расширяемым, \global
запускает его расширение и вы получаете \global\let\foo\bar
то, что хотели.
С другой стороны, \pgfmathsetmacro
определяется pgfmathcalc.code.tex
по
\def\pgfmathsetmacro#1#2{%
\begingroup%
\pgfmathparse{#2}%
\let#1=\pgfmathresult
\pgfmath@smuggleone{#1}%
\endgroup%
}
\global
поэтому перед ним определенно нельзя добавлять .
Самый простой способ — сказать:
\pgfmathparse
(\AverageValue * \arabic{NumberOfValidEnteries} + \NewData) /
(\arabic{NumberOfValidEnteries} + 1)
}%
\global\let\AverageValue\pgfmathresult
поскольку \pgfmathparse
сохраняет результат в \pgfmathresult
.