如何使用 pgfmathdeclarefunction 来定义新的 pgf 函数?

如何使用 pgfmathdeclarefunction 来定义新的 pgf 函数?

我想为 定义新函数,以便pgf在 中使用它pgfplots。我正在尝试创建一个单位脉冲函数 p(x),其值从 x=0 到 x=1 为 1,其他地方为 0。

我读过pgf 手册关于自定义数学引擎(第 65 节,第 541 页),但我可能误解了一些东西 =P

此代码不起作用:

\documentclass{minimal}
\usepackage{pgfplots}

\pgfmathdeclarefunction{p}{1}{%
  \pgfmathand{\pgfmathless{#1}{1}} {\pgfmathgreater{#1}{0}}%
}

\begin{document}

\begin{tikzpicture}
  \begin{axis}
    \addplot {p(x)};
  \end{axis}
\end{tikzpicture}

\end{document}

答案1

pgfmathparse我通过使用内部让它工作pgfmathdeclarefunction (我不知道这是否是你应该做的,但我现在很满意)

我也可以使用 来在本地定义它declare function

\documentclass{letter}
\usepackage{pgfplots}
\usepackage{setspace}
\doublespacing

\pgfmathdeclarefunction{p}{1}{%
  \pgfmathparse{and(#1>0, #1<1)}%
}

\begin{document}

My pgf version is: \pgfversion

p(0.2) is \pgfmathparse{p(0.2)}\pgfmathresult

p(2) is \pgfmathparse{p(2)}\pgfmathresult

Plot of p(x):

\begin{tikzpicture}
  \begin{axis}
    \addplot[domain=-5:5, samples=50]{p(x)};
  \end{axis}
\end{tikzpicture}

Using declare function to define localp(x):

\begin{tikzpicture}
[
  declare function={
    localp(\t) = and(\t > 0, \t < 1);
  }
]
  \begin{axis}
    \addplot[domain=-5:5, samples=50]{localp(x)};
  \end{axis}
\end{tikzpicture}

\end{document}

单位脉冲图

答案2

我想我可以对这里的问题提供更多见解。

首先的好消息是:提供\begin{axis}[use fpu=false]将使您能够使用所有自定义数学函数(我猜,只要它们在 pgf 中工作)。

现在详细介绍一下:让我总结一下讨论的状态:当我们在 pgfplots 中使用自定义数学函数时,我们有

  1. 包含 `\pgf@x=#1pt` 的解决方案导致
    
    ! Illegal unit of measure (pt inserted).
     
                       Y
    l.24      \addplot[domain=-5:5, samples=50]{double(x)};
    
  2. 使用 `\pgfmathmultiply{#1}{#1}` 的解决方案有效
  3. 使用 `\pgfmathparse` 的解决方案同样有效
  4. 使用 `\pgfmathand{\pgfmathless{#1}{1}}{\pgfmathgreater{#1}{0}}` 的解决方案失败了(在我的例子中,`!Extra else` 出现了一些奇怪的问题

问题是由于 PGFPlots 的初始配置为“use fpu=true”造成的。fpu 是一个 PGF 库;它用单精度浮点之类的东西替换了数学模块。

只要用户贡献的数学函数仅依赖于高级数学函数(如\pgfmathparse\pgfmathmultiply如上所述),代码库就会透明地使用 FPU - 并且一切都是一致的。

但是,一旦使用 TeX 寄存器,情况就会变得不同:写入\pgf@x=#1pt意味着第一个参数被解释为范围为 -16000...16000(大致)的定点数。使用use fpu=true,两者本质上都被违反:fpu 既没有定点数,也不限于此数据范围。出现错误消息是因为(在撰写本文时),浮点数的存储方式类似于1Y1.0e1Y “标志”与尾数分开。Y是第一个字符,其中\pgf@x=#1pt退出。但是请注意,FPU 足够智能,可以检测自定义函数的返回值是 TeX 寄存器数还是浮点数。但我不知道有任何方法可以询问“该函数是否会处理浮点数?”。

因此,正如前面提到的,use fpu=false禁用 FPU;然后 pgfplots 将使用 -16000...16000 范围内的定点数进行操作,并且所有数学函数都应该可以工作。

另一个解决方案是使用基本层数学函数,如\pgfmathmultiply。请注意,除非我弄错了,否则\pgfmathmultiply也会调用\pgfmathparse(这很昂贵)。用于\pgfmathmultiply@抑制参数解析(但是,\makeatletter在定义自定义函数之前需要)。

不幸的是,我不知道\pgfmathand{} {}解决方案为什么会失败。它在 PGF 中有效吗?

我希望这对您有帮助。

答案3

我建议使用这个非常简单的代码:

\documentclass{minimal}
\usepackage{tikz}
\makeatletter
\pgfmathdeclarefunction{p}{1}{\edef\pgfmathresult{\ifdim#1pt<\z@0\else\ifdim#1pt>1pt 0\else1\fi\fi}}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[very thin,color=gray] (-2,-2) grid (2,2);
\draw[color=blue] plot (\x,{p(\x)});
\end{tikzpicture}
\end{document}

答案4

我只用 pgfmanual 中的一个示例(第一个示例)修改了我的答案\pgfmathdeclarefunction。pgfmanual 中的这个示例适用于 pgf,而不适用于 pgfplots(为什么???)

带有 pgfplots 的部分出现 Latex 错误:./add_func_pgfplots.tex:77 非法测量单位(插入 pt)。

\documentclass{minimal}
\usepackage{pgfplots}
\makeatletter
\pgfmathdeclarefunction{double}{1}{%
 \begingroup 
  \pgf@x=#1pt\relax 
  \multiply\pgf@x by2\relax 
  \pgfmathreturn\pgf@x
 \endgroup 
}
\makeatother 
\begin{document}
\pgfmathparse{double(44.3)}\pgfmathresult 

 \begin{tikzpicture} 
   \draw plot [domain=0:5, samples=144, smooth] (\x,{double(\x)}); 
\end{tikzpicture} 

\begin{tikzpicture}
  \pgfmathdouble{1}
   \let\ra\pgfmathresult
   \draw (0,0) circle (\ra);% \ra is fine
 %  \begin{axis}
 %    \addplot[domain=-5:5, samples=50]{double(x)};
 %  \end{axis}  
\end{tikzpicture}

\end{document}

但是这个代码有效

 \documentclass{scrartcl}
 \usepackage{pgfplots}

\begin{document}

My pgf version is: \pgfversion 

\pgfmathdeclarefunction{double}{1}{
\begingroup
\pgfmathmultiply{#1}{#1} % instead of \pgfmathparse{#1*#1} from kristi
\endgroup 
} 

\begin{tikzpicture}
  \begin{axis}
   \addplot[domain=-5:5, samples=50]{double(x)};
 \end{axis}   
\end{tikzpicture}

\end{document}  

主要问题\pgfmathparse是,如果我们需要做很多循环,代码就会很慢

相关内容