Построение графика суммы функции в TikZ

Построение графика суммы функции в TikZ

Я пытаюсь построить функцию, которая является суммой другой функции на основе параметра.

Известным примером этого является «сумма квадратов», однако функции, которые мне действительно нужны, не имеют явной формулы.

Следующий пример показывает результат, который я хотел бы получить, и метод, с помощью которого я хотел бы его получить, но который, очевидно, не дает правильного результата.

\documentclass[border=10]{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
  % Explicit formula
  \pgfmathdeclarefunction{explicit_sum}{1}{%
    \pgfmathparse{(#1*(#1-1))/2}%
  }

  % The inner function
  \pgfmathdeclarefunction{square}{1}{%
    \pgfmathparse{#1*#1}%
  }

  % Compute the sum of another function
  % Does not work...
  \pgfmathdeclarefunction{manual_sum}{1}{%
    %Parameter should be integral
    \pgfmathtruncatemacro\cnt{#1}
    \pgfmathsetmacro\ret{0}
    \foreach \i in {1,...,\cnt} {
      \pgfmathsetmacro\ret{\ret + sum(\i)}
    }
    \pgfmathparse{\ret}
  }

  \begin{tikzpicture}
    \begin{axis}
      % Expected
      \addplot[samples at={1,...,10}] {explicit_sum(x)};

      % Does not work
      \addplot[samples at={1,...,10}] {manual_sum(x)};
    \end{axis}    
  \end{tikzpicture}

\end{document}

решение1

Если разрешено создать «невидимую» таблицу для определения значений x, а затем выполнить вычисления в другом столбце, то можно сделать следующее.

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    % Explicit formula
    \pgfmathdeclarefunction{explicit_sum}{1}{%
        \pgfmathparse{(#1*(#1-1))/2}%
    }
    \pgfplotstableset{
        % define how the 'x' column shall be filled
        % (in this case just with integers counting from 1)
        create on use/x/.style={
            create col/set list={1,...,100}
        },
        % -----
        % now you can either create here a column with your function ...
        create on use/fx/.style={
            create col/expr={(\thisrow{x})^2}
        },
        % ... and then accumulate the values here ...
        create on use/sum/.style={
            create col/expr accum={
                \pgfmathaccuma + \thisrow{fx}
            }{0},       % <-- start with `0'
        },
        % -----
        % ... or you accumulate directly with the function
        create on use/sum2/.style={
            create col/expr accum={
                \pgfmathaccuma + (\thisrow{x})^2
            }{0},       % <-- start with `0'
        },
        % -----
    }
    % here you create a new table using the columns you need and
    % with the first mandatory argument you specify the number of elements
    % the table should have
    % (so either `sum2' is redundant or (`fx' and `sum') are redundant)
    \pgfplotstablenew[
        columns={x,fx,sum,sum2},
    ]{10}{\loadedtable}
\begin{document}
%    % maybe it is useful to typeset the table for debugging purposes
%    \pgfplotstabletypeset[
%        columns={x,fx,sum,sum2},
%    ]{\loadedtable}
    \begin{tikzpicture}
        \begin{axis}[
            % added for debugging purposes or here to quicker check,
            % it one gets the desired output
            nodes near coords,
        ]
        % Expected
        \addplot+[samples at={1,...,10}] {explicit_sum(x)};

        % when the table is created, you can use the columns here
        \addplot table [x=x,y=sum] {\loadedtable};
        \end{axis}
    \end{tikzpicture}
\end{document}

изображение, показывающее результат кода выше

решение2

TL; DR, объявление функции должно быть

  \pgfmathdeclarefunction{manual_sum}{1}{%
    \pgfmathfloattoint{#1}\let\cnt\pgfmathresult%
    \pgfmathsetmacro\ret{0}%
    \foreach\i in{1,...,\cnt}{%
      \pgfmathsetmacro\ret{\ret+\i}         % summing integer itself
     %\pgfmathsetmacro\ret{\ret+square(\i)} % general case
      \xdef\ret{\ret}%
    }%
    \pgfmathparse{\ret}%
  }

В вашем коде есть две проблемы:

  • Во-первых, \foreachвводит вложенную группировку и \retоказывается в ловушке группы.
  • Во-вторых, посколькуактивирует FPU, \pgfmathtruncatemacro\cnt{#1}заставит \cntбыть 1.
    • (Это на самом делефлагв #1представительстве ФПУ.)
    • (флаг 1(Обозначает положительное число.)

Чтобы преодолеть первое препятствие, я обычно использую \xdefконтрабанду ценности. Также стоит отметить, чтопредставляет \pgfplotsforeachungrouped, который по сути является несгруппированной версией \foreach.

Для решения второго препятствия необходимо внимательно изучить руководство и определить \pgfmathfloattoint{#1}\let\cnt\pgfmathresultправильный способ выполнения работы.


это даст вам кривую, отличную от explicit_sum, и тогда вы поймете, что #1*(#1-1)/2это неверная формула.

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