【问题标题】:After how many iteration SecureRandom will generate all the number between given range?经过多少次迭代 SecureRandom 将生成给定范围之间的所有数字?
【发布时间】:2012-10-09 19:24:57
【问题描述】:

SecureRandom 需要多少次迭代才能生成给定范围内的所有数字。 例如。我正在生成 0-9 之间的随机数(包括两者)。然后经过多少次迭代后,所有数字(0、1、2、...、9)至少出现一次。

【问题讨论】:

  • 应该是随机的。所以它可能是 10 或 1000000(尽管后者不太可能)
  • @JBNizet 前者也极不可能。 :)
  • 您问这个问题有什么特殊的原因吗?例如,您的目标是实际按随机顺序排列数字 0-9 吗?
  • 请出示您的代码,以便我们了解您是如何生成数字的。

标签: java random


【解决方案1】:

如前所述,无法保证生成这十个值需要多长时间。然而,概率法则确实使得它更可能需要接近 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;
            }
        }
    }

}

【讨论】:

    【解决方案2】:

    假设 SecureRandom 是完全随机的(它的 Secure 部分所追求的)答案是,没有给定的数字可以保证所有数字至少出现一次。

    【讨论】:

    • 我对java.security.SecureRandom特别感兴趣,它是一个伪随机数生成器。
    • @CodeDance 不,它不是一个伪随机数生成器。来自SecureRandom 的文档:“此外,SecureRandom 必须产生非确定性输出。”。因此至少有一些保证的随机性,因此它不是伪随机的。
    • SecureRandom 有时 是伪随机的:当它使用SHA1PRNG 算法时。默认情况下,它使用非确定性源来设置种子,但您也可以指定种子。相关:SecureRandom safe seed in Java
    【解决方案3】:

    正如 CrazyCasta 所说,正确答案是 - 没有给定的数字。

    引用 Scott Adams 的话:这就是随机性的问题,你永远无法确定 :)

    http://dilbert.com/fast/2001-10-25/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 2019-11-29
      相关资源
      最近更新 更多