edit:
Глядя на wolfram, кажется, что проблема размера nxm может быть решена с помощью:
public static BigDecimal getHypergeometricDistribution(//
int a[][], int scale, int roundingMode//
) throws OutOfMemoryError, NullPointerException {
ArrayList<Integer> R = new ArrayList<Integer>();
ArrayList<Integer> C = new ArrayList<Integer>();
ArrayList<Integer> E = new ArrayList<Integer>();
int n = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if (a[i][j] < 0)
return null;
n += a[i][j];
add(C, j, a[i][j]);
add(R, i, a[i][j]);
E.add(a[i][j]);
}
}
BigDecimal term1 = //
new BigDecimal(multiplyFactorials(C).multiply(multiplyFactorials(R)));
BigDecimal term2 = //
new BigDecimal(getFactorial(n).multiply(multiplyFactorials(E)));
return term1.divide(term2, scale, roundingMode);
}
Для getBinomialCoefficient, getFactorial и комментариев, посмотрите мой гист .
Факториалы растут очень быстро , например:
Пример Wolfram:
int[][] a = { { 5, 0 }, { 1, 4 } };
System.out.println(hdMM.getHypergeometricDistribution(a, 60, 6));
приведет к:
0.023809523809523809523809523809523809523809523809523809523810
edit 2:
Мой метод быстрый, но неэффективный по памяти, если сумма входных матричных элементов превышает 10000, это может быть проблемой.Причиной этого является запоминание факториалов.
Почти эквивалентная функция в Mathematica, без этой проблемы:
FeT1::usage = "Fisher's exact Test, 1 tailed. For more information:
http://mathworld.wolfram.com/FishersExactTest.html";
FeT1[a_List, nr_Integer: 6] := Module[{},
SumRow[array_] := Total[Transpose[array]];
SumTotal[array_] := Total[Total[array]];
SumColumn[array_] := Total[array];
TF[list_] := Times @@ (list!);
N[(TF[SumColumn[a]]*TF[SumRow[a]])/(SumTotal[a]!* TF[Flatten[a]]), nr]
];
и пример использования:
a = {{5, 0}, {1, 4}};
FeT1[a, 59]
приведет к
0.023809523809523809523809523809523809523809523809523809523810
Mathematica также имеет статистические пакеты, в которых реализован точный тест Фишера.ИМХО, написание этого на Java может быть на 20% быстрее, но необходимые усилия составляют около 200%, а время разработки - 400%.