【问题标题】:Generation of the same sequence of random numbers生成相同的随机数序列
【发布时间】:2011-10-27 00:56:21
【问题描述】:

我想在 java 中生成随机数,我知道我应该使用像 Math.random() 这样的现有方法,但是,我的问题是:如何在每次运行我的应用程序时生成相同的数字序列? 例子:生成的序列为:0.9,0.08,0.6 所以我希望每次执行此方法时都会生成此序列..

【问题讨论】:

    标签: java


    【解决方案1】:

    当然 - 只需创建 Random 的实例而不是使用 Math.random(),并始终指定相同的种子:

    Random random = new Random(10000); // Or whatever seed - maybe configurable
    int diceRoll = random.nextInt(6) + 1; // etc
    

    请注意,如果您的应用程序涉及多个线程,则会变得更加困难,因为时间变得难以预测。

    这利用了 Randompseudo-random number generator 的优势 - 换句话说,每次你向它询问新结果时,它都会操纵内部状态给你一个看起来随机的序列,但知道种子(或者实际上当前的内部状态)这是完全可以预测的。

    【讨论】:

    • 在线程的情况下,您可以为每个线程提供自己的随机数(具有固定种子),或者如果您仅使用几个数字,则为每个随机数(具有固定种子)中的每个线程提供一个预先填充的列表。但是,如果线程相互交互,这种方法也将不再有效。
    【解决方案2】:

    重复使用同一个种子的例子。

    public static void main(String... args) throws IOException {
        printDoublesForSeed(1);
        printDoublesForSeed(128);
        printDoublesForSeed(1);
        printDoublesForSeed(128);
    }
    
    private static void printDoublesForSeed(long seed) {
        double[] doubles = new double[10];
        Random rand = new Random(seed);
        for (int j = 0; j < doubles.length; j++) {
            doubles[j] = (long) (rand.nextDouble() * 100) / 100.0;
        }
        System.out.println("doubles with seed " + seed + " " + Arrays.toString(doubles));
    }
    

    打印

    doubles with seed 1 [0.73, 0.41, 0.2, 0.33, 0.96, 0.0, 0.96, 0.93, 0.94, 0.93]
    doubles with seed 128 [0.74, 0.53, 0.63, 0.41, 0.21, 0.2, 0.33, 0.74, 0.17, 0.47]
    doubles with seed 1 [0.73, 0.41, 0.2, 0.33, 0.96, 0.0, 0.96, 0.93, 0.94, 0.93]
    doubles with seed 128 [0.74, 0.53, 0.63, 0.41, 0.21, 0.2, 0.33, 0.74, 0.17, 0.47]
    

    编辑一个有趣的随机种子滥用。

    public static void main(String ... args) {
        System.out.println(randomString(-6225973)+' '+randomString(1598025));
    }
    
    public static String randomString(int seed) {
        Random rand = new Random(seed);
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<5;i++)
            sb.append((char) ('a' + rand.nextInt(26)));
        return sb.toString();
    }
    

    打印

    hello world
    

    【讨论】:

    • 我喜欢 hello world 示例。我认为没有更好的解决方案可以强制所有可能的种子找到正确的种子?编辑:显然不是,我不应该在喝第一杯咖啡之前写东西:o
    【解决方案3】:

    您需要为随机数生成器播种。

    Random random = new Random(aFixedNumber);
    random.nextInt();  // will always be the same
    

    【讨论】:

      【解决方案4】:

      Math.random 只是 java.util.Random 类的包装器。第一次调用 Math.random 时,会创建 java.util.Random 类的实例。

      现在,大多数 API 不公开任何 true 随机数生成器,因为它们无法在软件中实现。相反,他们使用 pseudo-random 数字生成器,该生成器使用一堆公式生成一系列看似随机的数字。这就是java.util.Random 所做的。但是,每个伪随机数生成器都需要先播种。如果您有两个伪随机数生成器,它们使用相同的算法并使用相同的种子,它们将产生相同的输出。

      默认情况下,java.util.Random 使用自 1970 年 1 月 1 日以来的毫秒数作为种子。因此,每次您启动程序时,它都会产生不同的数字(除非您管理它以在 1 毫秒内启动 java)。因此,您的问题的解决方案是创建自己的 java.util.Random 实例并自己播种:

      import java.util.Random;
      
      class ... {
          Random randomNumberGenerator = new Random(199711);
      
          public void ...()
          {
              int randomInt = randomNumberGenerator.nextInt();
              double randomDouble = randomNumberGenerator.nextDouble();
          }
      }
      

      randomNumberGenerator 将始终输出相同的数字序列,只要您不更改种子(199711)。

      【讨论】:

        【解决方案5】:

        我会将数字硬编码到应用程序中。这会占用更多内存,但速度更快。

        只需将随机数打印到终端,然后将它们复制粘贴到您的代码中。

        一定要留下评论来解释你做了什么,否则对于不知情的读者来说,它们就像黑魔法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-30
          • 1970-01-01
          • 2015-11-23
          • 2015-03-08
          • 2021-12-31
          • 1970-01-01
          相关资源
          最近更新 更多