Я использую тест Apache Commons Math Kolmogorov-Smirnov, чтобы определить, является ли образец, который производит мой ГСЧ, равномерным распределением.
Я использую UniformIntegerDistribution
для получения равномерного распределения и Я получаю образец 2000000 целых чисел. Затем я помещаю их в double[]
, который я производю из своих номеров RNG 2000000, и помещаю их в double[]
.
. Я нанес на график образец и вижу, что он однородный. но тест KS дает мне p-значение 0,0, которое указывало бы на то, что нулевая гипотеза о двух взятых из одного и того же распределения (т. е. Uniform) является недействительной. Это означает, что мой образец RNG не соответствует равномерному распределению.
double alpha = test.kolmogorovSmirnovTest(a, b);
дает мне alpha = 0.0
И Javado c метода читает:
Вычисляет значение p или наблюдаемый уровень значимости теста Колмогорова-Смирнова с двумя выборками, оценивая нулевую гипотезу о том, что x и y являются выборками, взятыми из одного и того же распределения вероятности.
Таким образом, я ожидаю, что значение p будет высоким, учитывая, что я вижу, что график является четко однородным.
IntegerDistribution uniform = new UniformIntegerDistribution(1, 81);
ArrayList<Integer> lis = new ArrayList<>();
int i = 0;
while (i < 100000) {
//Creates a list of 20 numbers ε [1,80]
List<Integer> l = ls.createRandomNumbersInclusive(80, 20);
lis.addAll(l);
Assertions.assertFalse(l.stream().anyMatch(it -> it > 80));
Assertions.assertFalse(l.stream().anyMatch(it -> it < 1));
i++;
}
KolmogorovSmirnovTest test = new KolmogorovSmirnovTest();
var sample = uniform.sample(2000000);
List<Integer> ll = new ArrayList<>();
double[] a = new double[2000000];
for(var j = 0; j<2000000; j++) {
a[j] = sample[j];
}
double[] b = lis.stream().map(it -> Double.valueOf(it)).mapToDouble(Double::doubleValue).toArray();
var alpha = test.kolmogorovSmirnovTest(a, b);
System.out.println("Alpha "+ alpha); //This gives me 0.0
/** I am doing the below to get the count per numbers [1,80] and plot them.
* I see them being uniform
* 1 ===
* 2 ===
* ...
* 80 ===
*/
Map<Integer, Long> result = lis.stream().collect(Collectors.groupingBy(it -> it, Collectors.counting()));
Меня беспокоит то, что если я создам new UniformIntegerDistribution
и получить sample2
, а затем поместить его в test.kolmogorovSmirnovTest(a, b);
, я действительно получаю значение p, близкое к 1, что я и ожидаю.
Я либо делаю что-то не так с Java или в числах, производимых ГСЧ, есть что-то, чего я не получаю.
Код для createRandomNumbersInclusive
-
public List<Integer> fetchNumberList(final int drawNumberMin, final int drawNumberMax, final int drawNumberCount) {
final List<Integer> range = new ArrayList<Integer>();
for (int i = drawNumberMin; i <= drawNumberMax; i++) {
range.add(i);
}
Collections.shuffle(range, rng);
return new ArrayList<Integer>(range.subList(0, drawNumberCount));
}
, а для ГСЧ - rng = SecureRandom.getInstance("NativePRNGNonBlocking");