我的目的是绘制函数的一阶导数,如下所示这方法:
f'(x) = (f(x + dx) - f(x))/dx
。
我的函数有点长,所以我想知道是否可以将其保存在宏(或类似的东西)中,然后稍后再调用它
\pgfmathsetmacro{\f}{\A * \b * ((exp(-\b*(x))/(\p-\b)) + (exp(-\p*(x))/(\b-\p)))};
produces the error
*! Package PGF Math Error: Unknown function `x' (in '1* 0.7* ((exp(-0.7*(x))/(0.*
最小“工作”示例
\documentclass[12pt]{article}
\usepackage{tikz}
\usepackage{pgfplots}
\begin{document}
\begin{figure}
\centering
\begin{tikzpicture}
\pgfmathsetmacro{\b}{0.7};
\pgfmathsetmacro{\p}{0.4};
\pgfmathsetmacro{\A}{1};
%\pgfmathsetmacro{\f}{\A * \b * ((exp(-\b*(x))/(\p-\b)) + (exp(-\p*(x))/(\b-\p)))}; <-- failing attempt
\begin{axis}[
width=8cm, height=6cm,
xmin=0.003, xmax=10,
ymin=-0.2, ymax=0.8,
xtick=\empty, ytick=\empty,
axis lines=middle,
x label style={at={(axis cs:10,0)},anchor=west},
y label style={at={(0,1)},above},
xlabel={$t$}, ylabel={$r$},
clip=false
]
\addplot [red, very thick, samples=100, smooth,domain=0.003:10]
{ \A * \b * ((exp(-\b*(x))/(\p-\b)) + (exp(-\p*(x))/(\b-\p))) }; %
\end{axis}
\end{tikzpicture}
\end{figure}
\end{document}
我希望可以计算导数
(\A * \b * ((exp(-\b*(x+0.01))/(\p-\b)) + (exp(-\p*(x+0.01))/(\b-\p))) - \f)/0.01
或者,如果可能的话,用更简单的方法
答案1
首先,请注意以下几点:
\pgfmathsetmacro{\b}{0.7};
\pgfmathsetmacro{\p}{0.4};
\pgfmathsetmacro{\A}{1};
这里不应该有,;
因为这些不是 Ti钾Z 也不是像、、等pgfplots
语句。这些分号是导致 TeX 终端输出中出现以下错误信息(3 次)的原因:\path
\draw
\addplot
缺少字符:nullfont 字体中没有 ;!
另外,虽然使用\pgfmathsetmacro
是正确的,但对于直接以十进制形式写入的简单常量来说,它是一种繁重的机器。我建议使用\def
,这将是等效的,但速度更快。
(不过要小心单字母控制序列......宏就像\c
或\i
在 LaTeX 中有一个标准定义;在某些情况下,覆盖它们时可能会遇到问题。也就是说,像这里这样的局部定义 + 大部分计算代码可能“不是太不安全”。)。
pgfmath 的declare function
密钥
您正在寻找的工具是/pgf/declare function
(参见自定义数学引擎在里面钛钾Z & PGF 手册)。
使用此工具和解析步长为 0.1,您的想法是:
\documentclass[tikz,border=2mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\begin{document}
\begin{tikzpicture}[
declare function = {
f(\x) = \A * \b * ((exp(-\b*(\x))/(\p-\b)) + (exp(-\p*(\x))/(\b-\p)));},
]
\def\b{0.7}
\def\p{0.4}
\def\A{1}
\begin{axis}[
width=8cm, height=6cm, ymin=-0.15, ymax=0.7,
axis lines=middle,
x label style={at={(axis cs:10,0)}, anchor=west},
y label style={at={(0,1)}, above},
xlabel={$t$}, ylabel={$r$},
]
\addplot[red, very thick, samples=100, smooth, domain=0.003:10]
{ f(x) };
\addplot[blue, very thick, samples=100, smooth, domain=0.003:10]
{ (f(x + 0.1) - f(x)) / 0.1 };
\end{axis}
\end{tikzpicture}
\end{document}
如果像您的问题中那样使用 0.01 步长,则计算精度较低会导致结果不太令人满意:
为了\fpeval
获得更好的数值精度
\fpeval
使用(不是来自pgfmath
,特别是不使用库)以 0.01 步长可以获得良好的结果fpu
。这种技术速度较慢,而且以这种方式给出“导数”的可用表达式更为麻烦,但结果看起来不错:
\documentclass[tikz,border=2mm]{standalone}
\usepackage{xfp} % not needed if the LaTeX kernel is from 2022-06-01 or later
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\pgfmathdeclarefunction{g}{1}{%
\begingroup
\pgfmathfloattofixed{#1}%
\let\x\pgfmathresult
\edef\pgfmathresult{%
\fpeval{
(\A * \b * ((exp(-\b*(\x + 0.01))/(\p-\b)) + (exp(-\p*(\x + 0.01))/(\b-\p)))
- (\A * \b * ((exp(-\b*(\x))/(\p-\b)) + (exp(-\p*(\x))/(\b-\p)))))
/ 0.01}%
}%
\pgfmathsmuggle\pgfmathresult
\endgroup
}
\begin{document}
\begin{tikzpicture}[
declare function = {
f(\x) = \A * \b * ((exp(-\b*(\x))/(\p-\b)) + (exp(-\p*(\x))/(\b-\p)));},
]
\def\b{0.7}
\def\p{0.4}
\def\A{1}
\begin{axis}[
width=8cm, height=6cm, ymin=-0.15, ymax=0.7,
axis lines=middle,
x label style={at={(axis cs:10,0)}, anchor=west},
y label style={at={(0,1)}, above},
xlabel={$t$}, ylabel={$r$},
]
\addplot[red, very thick, samples=100, smooth, domain=0.003:10]
{ f(x) };
\addplot[blue, very thick, samples=100, smooth, domain=0.003:10]
{ g(x) };
\end{axis}
\end{tikzpicture}
\end{document}