我创建了一个简单的动画来说明我的代码如何线性化一个函数。我使用 TikZ 和 pgfplots 创建了动画。由于我对这两个软件包都很陌生,所以我肯定没有使用所有的功能。我想听听大家对我如何使用循环功能来改进这个动画的反馈。
我目前的实现是这样的:
\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{frame}[fragile]{Frame title}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = 0.0,
ymin = 0.0,
ymax = 4.0,
]
\addplot[ black, samples=200] {1/sqrt(x)};
\only<2->{\addplot[only marks, color=black,fill=white,samples at={0.10}]{1/sqrt(x)}; node 1}
\only<2->{\addplot[only marks, color=black,fill=white,samples at={4.0}]{1/sqrt(x)};}
\only<3>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (4.0, 1/sqrt{4.0});}
\only<4->{\addplot[only marks, color=black,fill=white,samples at={1.95}]{1/sqrt(x)};}
\only<4->{\draw[thick, dashed, color=red] (1.95, 1/sqrt{1.95}) -- (4.0, 1/sqrt{4.0});}
\only<4>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (1.95, 1/sqrt{1.95});}
\only<5->{\addplot[only marks, color=black,fill=white,samples at={0.925}]{1/sqrt(x)};}
\only<5->{\draw[thick, dashed, color=red] (0.925, 1/sqrt{0.925}) -- (1.95, 1/sqrt{1.95});}
\only<5>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.925, 1/sqrt{0.925});}
\only<6->{\addplot[only marks, color=black,fill=white,samples at={0.4125}]{1/sqrt(x)};}
\only<6->{\draw[thick, dashed, color=red] (0.4125, 1/sqrt{0.4125}) -- (0.925, 1/sqrt{0.925});}
\only<6>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.4125, 1/sqrt{0.4125});}
\only<7>{\addplot[only marks, color=black,fill=white,samples at={0.15625}]{1/sqrt(x)};}
\only<7>{\draw[thick, dashed, color=red] (0.15625, 1/sqrt{0.15625}) -- (0.4125, 1/sqrt{0.4125});}
\only<7>{\draw[thick, dashed, color=red] (0.10, 1/sqrt{0.10}) -- (0.15625, 1/sqrt{0.15625});}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}
我确信有更好的方法可以做到这一点。我知道如何在代码中执行此操作以获取实际数据,但我不确定在 TikZ/pgfplots 中执行此操作的咒语。如何?我感兴趣的几件事:
- 我如何存储该函数以便每次我想要计算一个点时不必重复它?
- 我如何使用循环来自动化这个?(这里有太多重复的代码。)
- 我可以不使用投影仪来做到这一点吗?
我在这里使用的算法是,给定一个函数(本例中为 1/sqrt(x))和该曲线上的两个点。在这两点之间画一条直线。如果该直线与曲线的近似值很差:
- 在两个原始点的中间选取一点。
- 从中点到端点之间画线。
- 对每一组新点重复此操作,直到线性近似“足够好”。
现在,我并不真正关心如何确定“足够好”,这比这个动画所需的还要多。我真的只想迭代一定次数(在本例中为 5 次),因为这样至少在视觉上可以达到目的。
答案1
事实上,它可以被简化。
\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\tikzset{declare function={myf(\x)=1/sqrt(\x);}}
\begin{document}
\begin{frame}[fragile]{Frame title}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = 0,
ymin = 0.0,
ymax = 4.0,
]
\addplot[ black, samples=200,domain=0.1:4] {myf(x)};
\xdef\Lst{(4,{myf(4)}) }
\only<1>{
\addplot[thick,dashed, color=red] coordinates {\Lst (0.1,{myf(0.1)}) };
\addplot[only marks,mark=o,clip=false] coordinates {\Lst (0.1,{myf(0.1)}) };
}
\foreach \X in {2,3,4}
{
\xdef\Lst{\Lst ({8*pow(2,-\X)},{myf(8*pow(2,-\X))}) }
\only<\X>{
\addplot[thick,dashed, color=red,] coordinates {\Lst (0.1,{myf(0.1)})};
\addplot[only marks,mark=o,clip=false] coordinates {\Lst (0.1,{myf(0.1)}) };
}
}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}
使用@percusse 的建议并真正将函数绘制为 4,输出几乎相同:
\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\tikzset{declare function={myf(\x)=1/sqrt(\x);}}
\begin{document}
\begin{frame}[fragile]{Frame title}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = 0,
ymin = 0.0,
ymax = 4.0,
]
\addplot[ black, samples=200,domain={1/16}:4] {myf(x)};
\xdef\Lst{4}
\only<1>{
\addplot[thick,dashed, color=red,samples at={\Lst,0.0625}] {myf(x)};
\addplot[only marks,mark=o,clip=false,samples at={\Lst,0.0625}] {myf(x)};
}
\foreach \X [evaluate={\Y=1/16+2*(4-1/16)*pow(2,-\X)}] in {2,3,4}
{
\xdef\Lst{\Lst,\Y}
\only<\X>{
\addplot[thick,dashed, color=red,samples at={\Lst,0.0625}] {myf(x)};
\addplot[only marks,mark=o,clip=false,samples at={\Lst,0.0625}] {myf(x)};
}
}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}
答案2
在对括号和圆括号进行了一些修改之后,我将你的 mwe 修改为这样
(但我知道这并没有回答 OP 关于执行循环的问题:它只显示了如何让原始 MWE 编译时没有错误)
\documentclass{beamer}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{frame}[fragile]{Frame title}
\begin{tikzpicture}
\begin{axis}[
ticks = none,
axis x line = bottom,
axis y line = left,
xmin = 0.0,
ymin = 0.0,
ymax = 4.0,
]
\addplot[ black, samples=200] {1/sqrt(x)};
\only<2->{\addplot[only marks, color=black,fill=white,samples at={0.10}]{1/sqrt(x)};}
\only<2->{\addplot[only marks, color=black,fill=white,samples at={4.0}]{1/sqrt(x)};}
\only<3>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (4.0, {1/sqrt(4.0)});}
\only<4->{\addplot[only marks, color=black,fill=white,samples at={1.95}]{1/sqrt(x)};}
\only<4->{\draw[thick, dashed, color=red] (1.95, {1/sqrt(1.95)}) -- (4.0, {1/sqrt(4.0)});}
\only<4>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (1.95, {1/sqrt(1.95)});}
\only<5->{\addplot[only marks, color=black,fill=white,samples at={0.925}]{1/sqrt(x)};}
\only<5->{\draw[thick, dashed, color=red] (0.925, {1/sqrt(0.925)}) -- (1.95, {1/sqrt(1.95)});}
\only<5>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.925, {1/sqrt(0.925)});}
\only<6->{\addplot[only marks, color=black,fill=white,samples at={0.4125}]{1/sqrt(x)};}
\only<6->{\draw[thick, dashed, color=red] (0.4125, {1/sqrt(0.4125)}) -- (0.925, {1/sqrt(0.925)});}
\only<6>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.4125, {1/sqrt(0.4125)});}
\only<7>{\addplot[only marks, color=black,fill=white,samples at={0.15625}]{1/sqrt(x)};}
\only<7>{\draw[thick, dashed, color=red] (0.15625, {1/sqrt(0.15625)}) -- (0.4125, {1/sqrt(0.4125)});}
\only<7>{\draw[thick, dashed, color=red] (0.10, {1/sqrt(0.10)}) -- (0.15625, {1/sqrt(0.15625)});}
\end{axis}
\end{tikzpicture}
\end{frame}
\end{document}
并且它有效。(在文章类中编译只有 tikz 代码比使用 beamer 要快得多,我不知道为什么)。
编辑但日志中有数十条溢出警告1/sqrt(0)
,感谢@marmot 提醒我注意这一点。使用
\addplot[ black, samples=200, domain=0.1:4] {1/sqrt(x)};
正如@marmot 的回答所修复的那样并显著加快处理速度!
以下是注释掉frame
、添加\def\only<#1>#2{#2}
和使用文章类的内容: