数学家协会
\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{arrows.meta}
\pgfplotsset{compat=1.15}
\begin{document}
\begin{tikzpicture}
[
declare function = {binom(\x,\y) = \x! / \y! / (\x - \y)!;},
declare function = {binompdf(\x,\y,\z) = binom(\x, \z) * \y^\z * (1 - \y)^(\x - \z);}
]
\begin{axis}
[
grid = none,
tick style = {black},
tick label style = {
/pgf/number format/use comma,
/pgf/number format/fixed,
/pgf/number format/fixed zerofill},
scaled ticks = false,
% x axis
xmin = 0, xmax = 0.01,
axis x line = middle, x axis line style = -{Stealth},
xlabel = $p$, xlabel style = {below},
xtick = {0, 0.001, ..., 0.01}, xticklabels = {},
extra x ticks = {0.001},
xticklabel style = {/pgf/number format/precision = 3},
% y axis
ymin = 0, ymax = 1.1,
axis y line = middle, y axis line style = -{Stealth},
ylabel = $P(X \ge 10)$, ylabel style = {left},
ytick = {0, 0.1, ..., 1.1}, yticklabels = {},
extra y ticks = {0.1},
]
\addplot[domain = 0 : 0.01, samples = 100] {0.8};
\addplot[domain = 0 : 0.01, samples = 100] {1 - binompdf(2100, x, 0) - binompdf(2100, x, 1) - binompdf(2100, x, 2) - binompdf(2100, x, 3) - binompdf(2100, x, 4) - binompdf(2100, x, 5) - binompdf(2100, x, 6) - binompdf(2100, x, 7) - binompdf(2100, x, 8) - binompdf(2100, x, 9)};
\end{axis}
\end{tikzpicture}
\end{document}
产生以下结果:
存在三个问题:
- 计算不太准确(见下面的 Maple 输出)。这可能是由于计算 2100! 时中间结果很大。
- LaTeX 需要很长时间来编译文档。
- 写第二条
\addplot
命令很不方便。有没有办法声明一个函数来进行累计?
答案1
这解决了所有三个问题。仅对于 2) 在一定程度上:
real 0m5.005s
user 0m4.964s
sys 0m0.036s
嗯,实际上我没有对原始代码进行计时。这是它,但在比用于上述计时的计算机慢约 20% 的计算机上。
real 3m56.351s
user 3m55.698s
sys 0m0.387s
因此,尽管情节仍然需要几秒钟,但速度提高了约 40 倍。
我们用xintexpr
:
编辑:原始答案对 进行了一些不必要的修改\pgfmathfloatvalueof
。但它可以直接使用。我在其他地方犯了一些错误,导致我认为它需要更改以使其可扩展。但通常意义上的可扩展性就足够了。因此,下面\FVof
就是将输入从 传递到 所需的全部pgf
内容\xintfloatexpr
。
\documentclass{article}
\usepackage{pgfplots}
\usetikzlibrary{arrows.meta}
\pgfplotsset{compat=1.15}
% I was very happy to find \pgfmathfloatvalueof in TikZ/pgf manual
\def\FVof(#1){\pgfmathfloatvalueof{#1}}
\usepackage{xintexpr}
\begin{document}
\begin{tikzpicture}
[
% original declarations
% declare function = {binom(\x,\y) = \x! / \y! / (\x - \y)!;},
% declare function = {binompdf(\x,\y,\z) = binom(\x, \z) * \y^\z * (1 - \y)^(\x - \z);}
% declaration using xintexpr.sty
declare function = {cumulbinompdf(\x,\y,\z) = \xintthefloatexpr
add(binomial(\FVof(\x),i) * \FVof(\y)^i * (1 -\FVof(\y))^(\FVof(\x)- i),
i = 0..\FVof(\z)
)
\relax;}
]
\begin{axis}
[
grid = none,
tick style = {black},
tick label style = {
/pgf/number format/use comma,
/pgf/number format/fixed,
/pgf/number format/fixed zerofill},
scaled ticks = false,
% x axis
xmin = 0, xmax = 0.01,
axis x line = middle, x axis line style = -{Stealth},
xlabel = $p$, xlabel style = {below},
xtick = {0, 0.001, ..., 0.01}, xticklabels = {},
extra x ticks = {0.001},
xticklabel style = {/pgf/number format/precision = 3},
% y axis
ymin = 0, ymax = 1.1,
axis y line = middle, y axis line style = -{Stealth},
ylabel = $P(X \ge 10)$, ylabel style = {left},
ytick = {0, 0.1, ..., 1.1}, yticklabels = {},
extra y ticks = {0.1},
]
\addplot[domain = 0 : 0.01, samples = 100] {0.8};
\addplot[domain = 0 : 0.01, samples = 100] {1 - cumulbinompdf(2100, x, 9)};
\end{axis}
\end{tikzpicture}
\end{document}
binomial
警告:该函数有一个缺陷,\xintfloatexpr
即它确实接受浮点输入,但是截断将它们转换为整数。它应该圆形的将它们转换为整数。同样,i = 0..Z
如果我没记错的话,构造将截断为整数Z
。它应该四舍五入。
在本例中,我认为变量是足够小的整数,因此在 pgf 处理中不会出现舍入误差,因此当它们达到\xintfloatexpr
截断时确实会产生误差2100
,而不是2099
每次都产生误差。我猜图形中不会显示出太大的差异(没有考虑过)。
它也适用于
declare function = {cumulbinompdf(\x,\y,\z) = \xintthefloatexpr
add(binomial(\FVof{\x},i) * \FVof{\y}^i * (1 -\FVof{\y})^(\FVof{\x}- i),
i = 0..\FVof{\z}
)
\relax;}
然后\let\FVof\pgfmathfloatvalueof
它只是一个别名。但我发现将上述内容定义\FVof
为宏并使用括号作为分隔符更加美观,这样宏定义中就不需要使用括号了。