Java随机生成器如何工作?

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

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

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

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

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

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

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

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

 new_state = (old_state * C1 + C2) modulo N 

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

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

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

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

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

是的,可以预测随机数生成器接下来会生成什么数字。 我已经看到这个叫做破解,破坏或攻击RNG。 搜索任何这些术语以及“随机数生成器”应该会产生很多结果。

阅读我们如何学习在线扑克作弊:软件安全研究,以获得有关如何攻击随机数发生器的出色第一手资料。 总而言之,作者根据在线扑克网站采用的错误改组算法找出了使用RNG的原因。 然后,他们通过抽样处理手来计算出RNG种子。 一旦他们拥有算法和种子,他们就知道在后来的洗牌后如何安排牌组。

您也可以参考此链接 。

检查java.util.Random如何工作以及它有多好用 ?:

换句话说,我们从一些开始或“种子”数字开始,理想情况下是“真正不可预测的”,并且在实践中它“足够不可预测”。 例如,在大多数系统上都可以使用自计算机开机以来的毫秒数甚至纳秒数。 然后,每当我们想要一个随机数时,我们将当前种子乘以一些固定数,a,再加上另一个固定数c,然后取结果模数为另一个固定数,m。 数字a通常很大。 这种随机数生成方法几乎可以追溯到计算的曙光1。 几乎所有你能想到的“随意”随机数生成器 – 从科学计算器到20世纪80年代的家用计算机到当前的C和Visual Basic库函数 – 都使用上述公式的一些变体来生成随机数。

并且还预测Java中的下一个Math.random()