Как добавить \global перед \pgfmathsetmacro?

Как добавить \global перед \pgfmathsetmacro?

Кажется, что нельзя добавить \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.

Связанный контент