Java随机生成器如何工作?

时间:2016-02-17 11:44:54

标签: java random jvm

我编写了模拟骰子滚动的程序

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

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

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

4 个答案:

答案 0 :(得分:14)

他们是伪随机数,这意味着对于一般意图和目的,他们足够随意。然而,它们是确定性的并且完全依赖于种子。以下代码将两次打印相同的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));

如果您可以选择种子,您可以先预先计算数字,然后使用相同的种子重置生成器,并且您事先知道出现的数字。

答案 1 :(得分:10)

  

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

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

new_state = (old_state * C1 + C2) modulo N

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

  

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

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

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

这是一个问题吗?那取决于你的应用程序需要什么。如果您需要难以预测的“随机”数字(例如,对于与安全性相关的算法),那么显然没有。如果这些数字将用于蒙特卡罗模拟,那么LCNG的内部自相关可能会使模拟失真。但是,如果你只是在制作单人纸牌游戏......也许并不重要。

答案 2 :(得分:1)

是的,可以预测随机数生成器接下来会生成什么数字。我已经看到这种情况称为破解,破坏或攻击RNG。搜索任何这些术语以及&#34;随机数生成器&#34;应该会产生很多结果。

阅读How We Learned to Cheat at Online Poker: A Study in Software Security,获取有关如何攻击随机数生成器的出色第一手资料。总而言之,作者根据在线扑克网站采用的错误改组算法找出了使用RNG的原因。然后他们通过抽样处理手来计算出RNG种子。一旦他们拥有了算法和种子,他们就会知道在后来的洗牌之后如何安排牌组。

您也可以参考此link

答案 3 :(得分:1)

检查How does java.util.Random work and how good is it?:

  

换句话说,我们从一些开始或'#34;种子&#34;开始。数字   理想情况下是真正无法预测的,并且实际上是   &#34;不可预测&#34;。例如,毫秒数或   甚至纳秒 - 自计算机开机以来就可以使用   大多数系统。然后,每次我们想要一个随机数,我们乘以   当前种子由一些固定数字,a,添加另一个固定数字,c,   然后将结果模数为另一个固定数,m。数字是   一般都很大。这种随机数生成方法又回来了   几乎到了计算的曙光1。几乎每一个&#34;休闲&#34;   您可以想到的随机数发生器 - 来自科学的   计算器到20世纪80年代家用电脑到当天的C和Visual Basic   库函数 - 使用上面公式的一些变体来生成   它的随机数。

还有Predicting the next Math.random() in Java