Java随机生成器是如何工作的?

2022-09-04 06:18:22

我编写了模拟掷骰子的程序

    Random r = new Random();
    int result = r.nextInt(6);
    System.out.println(result);

我想知道是否有办法“预测”下一个生成的数字,以及JVM如何确定下一个要生成的数字?

我的代码输出数字在任何JVM和操作系统上都会接近真正的随机数吗?


答案 1

它们是伪随机数,这意味着对于一般意图和目的,它们足够随机。然而,它们是确定性的,完全依赖于种子。以下代码将打印出相同的 10 个数字两次。

Random rnd = new Random(1234);
for(int i = 0;i < 10; i++)
    System.out.println(rnd.nextInt(100));

rnd = new Random(1234);
for(int i = 0;i < 10; i++)
    System.out.println(rnd.nextInt(100));

如果可以选择种子,则可以先预先计算数字,然后使用相同的种子重置生成器,您将提前知道得出的数字。


答案 2

我想知道是否有办法“预测”下一个生成的数字,以及JVM如何确定下一个要生成的数字?

绝对。该类实现为线性同余数生成器 (LCNG)。线性同余生成器的一般公式为:Random

new_state = (old_state * C1 + C2) modulo N

使用的精确算法在 javadocs 中指定。如果知道生成器1 的当前状态,则下一个状态是完全可预测的。Random

我的代码输出数字在任何JVM和操作系统上都会接近真正的随机数吗?

如果使用 ,则否。不适用于任何操作系统上的任何 JVM。Random

LCNG产生的序列绝对不是随机的,并且具有与真正的随机序列显着不同的统计属性。(该序列将具有很强的自相关性,如果您绘制对 的连续调用的结果,则会显示此序列。Random.nextInt()

这是一个问题吗?好吧,这取决于您的应用程序需要什么。如果您需要难以预测的“随机”数字(例如,对于与安全相关的算法),那么显然不是。如果这些数字将用于蒙特卡罗模拟,那么LCNG的自相关可能会扭曲模拟。但是,如果您只是构建一个纸牌游戏...也许没关系。


1 - 为了清楚起见,Random对象的状态由其实例变量的值组成;请参阅源代码。您可以使用调试器检查它们。在紧要关头,你可以访问它们,甚至使用Java反射更新它们,但我不建议这样做。不记录“上一个”状态。


推荐