gpt4 book ai didi

java - 超几何分布不能很好地工作java

转载 作者:行者123 更新时间:2023-12-01 09:26:55 26 4
gpt4 key购买 nike

我尝试使用超几何分布来计算概率,我在 math.stackexchange 中得到了一些帮助,但我在 java 中计算此问题时遇到问题

我不是这方面的专家,我一直试图弄清楚,但没有运气,我知道问题出在我的java代码上,因为当我在计算器上尝试公式时,我得到了正确的结果,在这种情况下是0.364

这就是公式

enter image description here

二项式是这样计算的

(K k) = K!/((K - k)! * k!)

这就是我尝试在 java 代码中复制它的方式

 public static void main(String[] args){
BigDecimal[] prob = HyperGeometricDistribution(20,2,50,5);
String _prob = prob[0] + "." + prob[1];
System.out.println(_prob);
}

private static BigDecimal fact(BigDecimal n) {
BigDecimal result = BigDecimal.ONE;
while (!n.equals(BigDecimal.ZERO)) {
result = result.multiply(n);
n = n.subtract(BigDecimal.ONE);
}
return result;
}

private static BigDecimal Binomial(int a, int b) {
return fact(BigDecimal.valueOf(a)).divide(fact(BigDecimal.valueOf(a-b)).multiply(fact(BigDecimal.valueOf(b))), BigDecimal.ROUND_DOWN);
}

// K : Number of Successes in Population
// k : number of Successes in Sample
// N : Population Size
// m : Sample Size
private static BigDecimal[] HyperGeometricDistribution(int K,int k, int N, int m){
return (Binomial(K,k).multiply(Binomial(N-K,m-k))).divideAndRemainder(Binomial(N,m));
}

这将打印 0.77,但正确答案是 0.364 Online Example

我将在android中使用它,我将在N中传递的最大值是3910,我需要使用BigDecimals,因为我需要计算3910!这是一个巨大的数字。

感谢任何帮助

最佳答案

divideAndRemainder() 的余数不是十进制表示的小数部分。您需要将余数除以实际除数。

但实际上,您不需要 BigDecimal。您只需要一种聪明的计算方法。让我们检查一下二项式系数的公式,例如 n=5, k=3。然后:

c(5, 3) = (5 * 4 * 3 * 2 * 1) / ((2 * 1) * (3 * 2 * 1))

如您所见,(n-k)! 部分完全抵消,最终得到

c(5, 3) = (5 * 4 * 3) / (3 * 2 * 1)
= 5/3 * 4/2 * 3/1

所以你只需要乘以k个分数即可。如果你总是减少分数,你就不需要很大的数字。事实上,超几何分布的计算也是一个分数,你可以再次减少一些东西以保持数字较小。下面是执行此操作的一些 C# 代码。它没什么花哨的,几乎完全可以翻译成 Java:

static class GCDHelper
{
public static long GCD(long a, long b)
{
while(b != 0)
{
var temp = b;
b = a % b;
a = temp;
}
return a;
}
}

class Fraction
{
public long Numerator;
public long Denominator;

public Fraction(long numerator, long denominator)
{
this.Numerator = numerator;
this.Denominator = denominator;
}

public void Reduce()
{
var gcd = GCDHelper.GCD(Numerator, Denominator);
Numerator /= gcd;
Denominator /= gcd;
}

public double ToNumber() { return (double)Numerator / Denominator; }
}

class Program
{
static void MultiplyBinomialCoefficient(int n, int k, bool inverse, Fraction f)
{
if (k > n / 2)
k = n - k;
for(int i = 1; i <= k; ++i)
{
if (!inverse)
{
f.Numerator *= n - i + 1;
f.Denominator *= i;
}
else
{
f.Denominator *= n - i + 1;
f.Numerator *= i;
}
f.Reduce();
}
}

static double Hypergeometric(int K, int k, int N, int m)
{
var f = new Fraction(1, 1);
MultiplyBinomialCoefficient(K, k, false, f);
MultiplyBinomialCoefficient(N - K, m - k, false, f);
MultiplyBinomialCoefficient(N, m, true, f);
return f.ToNumber();
}

static void Main(string[] args)
{
Console.WriteLine(Hypergeometric(20, 2, 50, 5));
}
}

结果:

0.364080877494384

仍有一些参数组合导致数字溢出。幸运的是,您只需将 long 变量替换为 BigInteger 变量(并相应地调整运算符)。其余的应该可以正常工作。

关于java - 超几何分布不能很好地工作java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39759704/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com