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

Dhr*_*goi 6 java openjdk-17

RandomGenerator 的默认算法即。从 JDK 18(自 17 起可用)开始,L32X64MixRandom 每次在单独调用时都会生成相同的数字。

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

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

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

jshell> java.util.random.RandomGenerator.of("L32X64MixRandom").nextInt(100, 999)
$15 ==> 526
Run Code Online (Sandbox Code Playgroud)

javadoc 听起来也没有任何特别的警告:

返回在指定原点(包括)和指定边界(不包括)之间伪随机选择的 int 值。

实现要求:默认实现检查origin 和bound 是否为正整数。然后调用 nextInt(),将结果限制为大于或等于原点且小于界限。如果bound是2的幂,那么限制就是一个简单的掩码操作。否则,通过调用 nextInt() 重新计算结果,直到结果大于或等于 origin 且小于bound。

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

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

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

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

jshell> java.util.random.RandomGenerator.of("L64X128MixRandom").nextInt(100, 999)
$13 ==> 844
Run Code Online (Sandbox Code Playgroud)

默认选择的这种程度的决定论是否有原因?

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

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

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

Jim*_*son 6

这是https://bugs.openjdk.java.net/browse/JDK-8282551中列出的错误

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

虽然这是一个仅链接的答案,但我相信这是合适的,因为其他人会遇到这个错误并在这里搜索。

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

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(" ")));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一次运行的输出:

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
Run Code Online (Sandbox Code Playgroud)