如前所述,无法保证生成这十个值需要多长时间。然而,概率法则确实使得它更可能需要接近 10 次迭代而不是 1,000,000 次。
我不够聪明,无法计算出实际的概率。但是,可以编写一个程序来通过反复运行问题来对空间进行采样,计算每次迭代的次数,然后您可以确定,例如,50% 的时间将花费少于 n 次迭代.
只是为了好玩,我写了一些东西来尝试这个问题,将问题运行 1,000,000 次并汇总结果。运行 3 次后,我的结果显示:
- 50% 的时间,它需要少于 27 次(包括)迭代(所有 3 次运行)。
- 在 90% 的情况下,它需要少于 44 次(含)迭代(所有 3 次运行)。
- 在 99% 的情况下,它需要少于 66 次(含)迭代(全部 3 次运行)。
- 在 99.9% 的情况下,它需要少于 88 次(包括)迭代(所有 3 次运行)。
- 每种情况下的最差运行情况不同,但 3 个值分别为 154 次迭代、156 次迭代和 170 次迭代。
这是我的检查代码。它使用 java.security.SecureRandom,但也包括使用 java.util.Random 的方法。
import java.security.SecureRandom;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
public class HowLong {
public static final int MAX_TO_GENERATE = 10;
public static final int TOTAL_RUNS = 1000000;
public static final int TP50 = (int)(TOTAL_RUNS * 0.50);
public static final int TP90 = (int)(TOTAL_RUNS * 0.90);
public static final int TP99 = (int)(TOTAL_RUNS * 0.99);
public static final int TP99_9 = (int)(TOTAL_RUNS * 0.999);
public static final int TP100 = (int)(TOTAL_RUNS * 1);
public static final String[] TP_NAMES = {"TP50", "TP90", "TP99", "TP99.9", "TP100"};
public static final int[] TPS = { TP50, TP90, TP99, TP99_9, TP100 };
public interface RandomSource {
int next();
}
public static class MathRandomSource implements RandomSource {
private final Random rand;
public MathRandomSource() {
rand = new Random();
}
public int next() {
return rand.nextInt(MAX_TO_GENERATE);
}
}
public static class SecureRandomSource implements RandomSource {
private final SecureRandom rand;
public SecureRandomSource() {
rand = new SecureRandom();
}
public int next() {
return rand.nextInt(MAX_TO_GENERATE);
}
}
public static int waitForTen() {
final boolean[] found = new boolean[MAX_TO_GENERATE];
int remaining = found.length;
final RandomSource source = new SecureRandomSource();
int iterations = 0;
while (remaining > 0) {
int next = source.next();
if (!found[next]) {
found[next] = true;
remaining -= 1;
}
iterations += 1;
}
return iterations;
}
public static void main(String[] args) {
System.out.println("Attempting to generate all numbers below: " + MAX_TO_GENERATE);
System.out.println("Performing n iterations: " + TOTAL_RUNS);
TreeMap<Integer, Integer> results = new TreeMap<Integer, Integer>();
for (int i = 0; i < TOTAL_RUNS; i += 1) {
Integer iterations = waitForTen();
Integer currentCount = results.get(iterations);
if (currentCount == null) {
results.put(iterations, 1);
} else {
results.put(iterations, currentCount + 1);
}
}
int currTP = 0;
int count = 0;
for (Map.Entry<Integer, Integer> entry: results.entrySet()) {
count += entry.getValue();
while (currTP < TPS.length && count >= TPS[currTP]) {
System.out.println(TP_NAMES[currTP] + ": " + entry.getKey());
currTP += 1;
}
}
}
}