如何编写以下方法?
dbinom(k, size=n, prob=P)pbinom(k, size=n, prob=P)...
我想知道在C#中是否有类似的内置算法或一些库可用?
谢谢。
回答:
嗯,你可以尝试自己创建这个程序。首先,由于我们将处理巨大的数字(阶乘),我们使用对数;而不是
dbinom(k, n, p) = = n! / k! / (n - k)! * pow(p, k) * pow(1 - p, n - k)
我们计算
log(dbinom(k, n, p)) = = log(n!) - log(k!) - log((n - k)!) + k * log(p) + (n - k) * log(1 - p)
最后,指数化它。从问题中我能看出,主要难点是log(n!).
我们可以为小的n
预先计算它,并在大参数的情况下使用Stirling近似:
public static class Distributions { private static Dictionary<int, double> s_LogFactorials = new Dictionary<int, double>(); static Distributions() { long p = 1; s_LogFactorials.Add(0, 0); for (int i = 1; i <= 20; ++i) s_LogFactorials.Add(i, Math.Log(p *= i)); } private static double LogFactorial(int value) { if (s_LogFactorials.TryGetValue(value, out double result)) return result; return Math.Log(2 * Math.PI * value) / 2 + value * Math.Log(value) - value + Math.Log(1 + 1 / 12.0 / value); } public static double dbinom(int k, int n, double p) { if (p < 0) throw new ArgumentOutOfRangeException(nameof(p)); else if (p > 1) throw new ArgumentOutOfRangeException(nameof(p)); if (k < 0 || n < 0 || k > n) return 0.0; else if (p == 0 || p == 1.0) return 0.0; double logResult = LogFactorial(n) - LogFactorial(k) - LogFactorial(n - k) + k * Math.Log(p) + (n - k) * Math.Log(1 - p); return Math.Exp(logResult); }}
一些测试:
Distributions.dbinom( 5, 9, 0.30) == 0.0735138179999999Distributions.dbinom( 21, 45, 0.48) == 0.116657747325863Distributions.dbinom( 63, 121, 0.54) == 0.0661504080311266Distributions.dbinom(1163, 2019, 0.52) == 5.15538389581199E-08
最后,如果你坚持使用数学库,你可以尝试Math.Net