RandomGenerator (L32X64MixRandom) 的默认算法每次生成相同的数字

Default algo for RandomGenerator (L32X64MixRandom) generates the same number each time

RandomGenerator 的默认算法,即。 L32X64MixRandom JDK 18(自 17 起可用),每次调用时生成相同的数字。

jshell> java.util.random.RandomGenerator.getDefault().nextInt(100,999)
 ==> 526

jshell> java.util.random.RandomGenerator.getDefault().nextInt(100,999)
 ==> 526

jshell> java.util.random.RandomGenerator.of("L32X64MixRandom").nextInt(100, 999)
 ==> 526

jshell> java.util.random.RandomGenerator.of("L32X64MixRandom").nextInt(100, 999)
 ==> 526

javadoc 也没有特别注意:

Returns a pseudorandomly chosen int value between the specified origin (inclusive) and the specified bound (exclusive).

Implementation Requirements: The default implementation checks that origin and bound are positive ints. Then invokes nextInt(), limiting the result to be greater that or equal origin and less than bound. If bound is a power of two then limiting is a simple masking operation. Otherwise, the result is re-calculated by invoking nextInt() until the result is greater than or equal origin and less than bound.

虽然其他算法(包括遗留算法)似乎具有可感知的随机性水平,例如

jshell> java.util.random.RandomGenerator.of("Random").nextInt(100,999)
 ==> 451

jshell> java.util.random.RandomGenerator.of("Random").nextInt(100,999)
 ==> 633

jshell> java.util.random.RandomGenerator.of("L64X128MixRandom").nextInt(100, 999)
 ==> 570

jshell> java.util.random.RandomGenerator.of("L64X128MixRandom").nextInt(100, 999)
 ==> 844

默认选择的这种确定性水平是否有原因?

编辑:行为 wrt。 streams 非常相似,初始值似乎总是相同的

jshell> java.util.random.RandomGenerator.getDefault().ints(100,999).limit(5).toArray()
 ==> int[5] { 526, 860, 258, 558, 820 }

jshell> java.util.random.RandomGenerator.getDefault().ints(100,999).limit(5).toArray()
 ==> int[5] { 526, 866, 448, 654, 684 }

这是 https://bugs.openjdk.java.net/browse/JDK-8282551

中列出的错误

它在 Java 19 中显示为已修复,并且有向 Java 17 和 18 的反向移植请求(https://bugs.openjdk.java.net/browse/JDK-8284185 已于 4/1/2022 解决),但尚不清楚向后移植的修复程序何时出现。

虽然这是一个 link-only 答案,但我认为它是合适的,因为其他人会遇到这个错误并在这里搜索。

为了完整起见,这里是我用于自己测试的代码:

private static String[] algs = 
    {"L128X1024MixRandom",
    "L128X128MixRandom",
    "L128X256MixRandom",
    "L32X64MixRandom",
    "L64X1024MixRandom",
    "L64X128MixRandom",
    "L64X128StarStarRandom",
    "L64X256MixRandom",
    "Random",
    "Xoroshiro128PlusPlus",
    "Xoshiro256PlusPlus"};

public static void main(String[] args) throws Exception {
    for (String alg : algs)
    {
        System.out.println("\nAlgorithm " + alg);
        for (int i=0; i<5; i++)
        {
            RandomGenerator g = RandomGenerator.of(alg);
            System.out.println(
                    g.ints(4,0,1000)
                     .boxed()
                     .map(x -> String.format("%5d",x))
                     .collect(Collectors.joining(" ")));
        }
    }
}

一个运行的输出:

Algorithm L128X1024MixRandom
  280   759    35    18
  824   668   554   754
  822   823   680   252
  629   718     3   392
   83   698   609   790

Algorithm L128X128MixRandom
  973   765   392   815
  495   164   744   418
  621   117   836   271
  787   819   463   825
  150   473   159   777

Algorithm L128X256MixRandom
   44    74   276   107
  703   802    41   743
  993   369   801   926
  456   754   138   870
  121   979   384    51

Algorithm L32X64MixRandom
  152   372   238    19
  152   334   300   942
  152   739   206   818
  152   284   200   628
  152   835   259   588

Algorithm L64X1024MixRandom
  782   247   982   974
  316   507   860   386
  571   563   166   646
  888   553   779   342
  121   750   764    68

Algorithm L64X128MixRandom
  706   202   985   510
  761   218   252   409
  992   844   765   861
  236   240   124   945
  680   983   444   689

Algorithm L64X128StarStarRandom
  619    40   879   489
  599   622   396   225
   76   359   104    31
  205   687   741   488
  141   732   509   172

Algorithm L64X256MixRandom
  929   338   648   606
  786   338   409   815
  750   363   713   722
  989   307    18   797
  154   266    20   552

Algorithm Random
  903   452   417    18
  838   888   609    32
  365   378   673   351
  758   413   665   566
  996   132   555   413

Algorithm Xoroshiro128PlusPlus
  145   864   592    22
  230    74    24   471
  596   302   294   734
  108   773   171   950
  716   694    87   726

Algorithm Xoshiro256PlusPlus
  563   528   572   853
  619   722   534    10
   87   306   594   525
  149   430   243   836
  578   938   802   539