期间我的调查的这个问题很好来自@Sentient,我发现了一个相当奇怪的问题:给定二项式参数 n=15
和 p=0.7
,@Sentient 的代码会产生一些概率值大于二! 这也可以通过其他参数来说明:
\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
\addplot[cyan, domain=0:1, samples=26, smooth]{normd(x, 25, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 25, 0.72)};
\end{axis}
\end{tikzpicture}\quad
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
\addplot[cyan, domain=0:1, samples=27, smooth]{normd(x, 26, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 26, 0.72)};
\end{axis}
\end{tikzpicture}
\end{document}
在左边,我设定n=25
和 p=0.72
;在右边,我设定n=26
和 p=0.72
。橙色曲线是函数生成的高斯近似值normaldensity
(公式可以在我之前的回答),它应该接近 normd
两张图中的青色曲线(由“正则化二项式”生成)。
然而,二项式概率的计算 normd
在右边偏离很大,产生的概率值大于 3!相反,左边的计算完全没问题。我相信 @marmot 在写的时候已经注意到了这个问题这个优秀的答案,因为伽马函数方法产生曲线非常不一样来自@Sentient(但非常接近高斯曲线)。
我的问题是:为什么会出现这个计算错误(但只是有时,例如,n = 23, 24 or 26
但不是n = 25
),以及我该如何修复它?
答案1
我忘了我自己的看法关于 TeX 如何存储实数(真尴尬!)。长话短说,在 normd
@Sentient 的原始函数中,\x*\n
被传递以进行阶乘计算。即使在我告诉PGFplots
使用
\x = 0, 1/\n, 2/\n, ... , \n/\n
很可能结果\x*\n
是没有任何1
到 的 整数 n-1
。这会导致阶乘结果荒谬,进而导致概率大于一。
因此,一个明显的解决方法是使用整数 \x
,然后像@marmot在评论中尝试的那样规范化x坐标。这种方法至少可以保证阶乘有一定的准确性。溢出问题是另一个我不想提起的麻烦。
\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\section*{The correct left is by luck}
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
\addplot[cyan, domain=0:1, samples=26, smooth]{normd(x, 25, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 25, 0.72)};
\addplot[red,only marks,samples at={0,1,...,25}](x/25,{binom(x, 25, 0.72)});
\end{axis}
\end{tikzpicture}\quad
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
\addplot[cyan, domain=0:1, samples=27, smooth]{normd(x, 26, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 26, 0.72)};
\addplot[red,only marks,samples at={0,1,...,26}](x/26,{binom(x, 26, 0.72)});
\end{axis}
\end{tikzpicture}
\section*{One should use integers for factorial calculations}
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
% \addplot[cyan, domain=0:1, samples=26, smooth]{normd(x, 25, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 25, 0.72)};
\addplot[red,only marks,samples at={0,1,...,25}](x/25,{binom(x, 25, 0.72)});
\end{axis}
\end{tikzpicture}\quad
\begin{tikzpicture}[
scale=0.88,
declare function={binom(\x,\n,\p)=\n!/(\x!*(\n-\x)!)*\p^\x*(1-\p)^(\n-\x);},
declare function={normd(\x,\n,\p)=binom(\x*\n,\n,\p);},
declare function={normaldensity(\x,\n,\p)=exp(-\n*(\x-\p)^2/(2*\p*(1-\p)))/sqrt(2*pi*\n*\p*(1-\p));}
]
\begin{axis}
% \addplot[cyan, domain=0:1, samples=27, smooth]{normd(x, 26, 0.72)};
\addplot[orange, domain=0:1, smooth]{normaldensity(x, 26, 0.72)};
\addplot[red,only marks,samples at={0,1,...,26}](x/26,{binom(x, 26, 0.72)});
\end{axis}
\end{tikzpicture}
\end{document}
作为一个经常与概率打交道的人,我PGFplots
很少程序我的分布函数。我发现使用统计软件生成的数据来绘制更容易(也更准确)PGFplots
。