Java 随机生成器是如何工作的?
How Java random generator works?
我写了模拟掷骰子的程序
Random r = new Random();
int result = r.nextInt(6);
System.out.println(result);
我想知道是否有办法 "predict" 下一个生成的数字以及 JVM 如何确定下一个生成的数字?
我的代码会在任何 JVM 和 OS 上输出接近真正随机数的数字吗?
它们是伪随机数,这意味着就一般意图和目的而言,它们足够随机。然而,它们是确定性的并且完全依赖于种子。以下代码将两次打印出相同的 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));
如果你可以选择种子,你可以先预先计算出数字,然后用相同的种子重新设置生成器,你会提前知道结果是什么数字。
是的,可以预测随机数生成器接下来会产生什么数字。我见过这叫做破解、破坏或攻击 RNG。搜索这些术语中的任何一个以及 "random number generator" 应该会得到很多结果。
阅读 How We Learned to Cheat at Online Poker: A Study in Software Security 以获得关于如何攻击随机数生成器的第一手资料。总而言之,作者根据在线扑克网站使用的错误洗牌算法弄清楚了正在使用的 RNG。然后,他们通过对发牌的手牌进行抽样计算出 RNG 种子。一旦他们有了算法和种子,他们就确切地知道在以后的洗牌之后将如何排列牌组。
你也可以参考这个link。
检查How does java.util.Random work and how good is it?:
In other words, we begin with some start or "seed" number which
ideally is "genuinely unpredictable", and which in practice is
"unpredictable enough". For example, the number of milliseconds— or
even nanoseconds— since the computer was switched on is available on
most systems. Then, each time we want a random number, we multiply the
current seed by some fixed number, a, add another fixed number, c,
then take the result modulo another fixed number, m. The number a is
generally large. This method of random number generation goes back
pretty much to the dawn of computing1. Pretty much every "casual"
random number generator you can think of— from those of scientific
calculators to 1980s home computers to currentday C and Visual Basic
library functions— uses some variant of the above formula to generate
its random numbers.
I want to know if there is a way to "predict" next generated number and how JVM determines what number to generate next?
当然可以。 Random
class 作为线性同余数生成器 (LCNG) 实现。线性同余生成器的一般公式为:
new_state = (old_state * C1 + C2) modulo N
Random
使用的精确算法在 javadocs 中指定。如果你知道生成器的当前状态1,下一个状态是完全可以预测的
Will my code output numbers close to real random at any JVM and OS?
如果您使用 Random
,则否。不适用于任何 OS 上的任何 JVM。
LCNG 产生的序列绝对不是随机的,并且具有与真正的随机序列明显不同的统计特性。 (该序列将具有很强的自相关性,如果您绘制连续调用 Random.nextInt()
的结果就会显示出来。)
这是个问题吗?好吧,这取决于您的应用程序需要什么。如果您需要 "random" 难以预测的数字(例如,对于与安全相关的算法),那么显然不是。如果这些数字将用于 Monte Carlo 模拟,那么 LCNG 的固有自相关可能会扭曲模拟。但是,如果您只是在构建单人纸牌游戏……这可能并不重要。
1 - 明确地说,Random
对象的状态由其实例变量的值组成;查看源代码。您可以使用调试器检查它们。在紧要关头,您可以访问它们,甚至可以使用 Java 反射更新它们,但我不建议这样做。 "previous"状态未记录。
我写了模拟掷骰子的程序
Random r = new Random();
int result = r.nextInt(6);
System.out.println(result);
我想知道是否有办法 "predict" 下一个生成的数字以及 JVM 如何确定下一个生成的数字?
我的代码会在任何 JVM 和 OS 上输出接近真正随机数的数字吗?
它们是伪随机数,这意味着就一般意图和目的而言,它们足够随机。然而,它们是确定性的并且完全依赖于种子。以下代码将两次打印出相同的 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));
如果你可以选择种子,你可以先预先计算出数字,然后用相同的种子重新设置生成器,你会提前知道结果是什么数字。
是的,可以预测随机数生成器接下来会产生什么数字。我见过这叫做破解、破坏或攻击 RNG。搜索这些术语中的任何一个以及 "random number generator" 应该会得到很多结果。
阅读 How We Learned to Cheat at Online Poker: A Study in Software Security 以获得关于如何攻击随机数生成器的第一手资料。总而言之,作者根据在线扑克网站使用的错误洗牌算法弄清楚了正在使用的 RNG。然后,他们通过对发牌的手牌进行抽样计算出 RNG 种子。一旦他们有了算法和种子,他们就确切地知道在以后的洗牌之后将如何排列牌组。
你也可以参考这个link。
检查How does java.util.Random work and how good is it?:
In other words, we begin with some start or "seed" number which ideally is "genuinely unpredictable", and which in practice is "unpredictable enough". For example, the number of milliseconds— or even nanoseconds— since the computer was switched on is available on most systems. Then, each time we want a random number, we multiply the current seed by some fixed number, a, add another fixed number, c, then take the result modulo another fixed number, m. The number a is generally large. This method of random number generation goes back pretty much to the dawn of computing1. Pretty much every "casual" random number generator you can think of— from those of scientific calculators to 1980s home computers to currentday C and Visual Basic library functions— uses some variant of the above formula to generate its random numbers.
I want to know if there is a way to "predict" next generated number and how JVM determines what number to generate next?
当然可以。 Random
class 作为线性同余数生成器 (LCNG) 实现。线性同余生成器的一般公式为:
new_state = (old_state * C1 + C2) modulo N
Random
使用的精确算法在 javadocs 中指定。如果你知道生成器的当前状态1,下一个状态是完全可以预测的
Will my code output numbers close to real random at any JVM and OS?
如果您使用 Random
,则否。不适用于任何 OS 上的任何 JVM。
LCNG 产生的序列绝对不是随机的,并且具有与真正的随机序列明显不同的统计特性。 (该序列将具有很强的自相关性,如果您绘制连续调用 Random.nextInt()
的结果就会显示出来。)
这是个问题吗?好吧,这取决于您的应用程序需要什么。如果您需要 "random" 难以预测的数字(例如,对于与安全相关的算法),那么显然不是。如果这些数字将用于 Monte Carlo 模拟,那么 LCNG 的固有自相关可能会扭曲模拟。但是,如果您只是在构建单人纸牌游戏……这可能并不重要。
1 - 明确地说,Random
对象的状态由其实例变量的值组成;查看源代码。您可以使用调试器检查它们。在紧要关头,您可以访问它们,甚至可以使用 Java 反射更新它们,但我不建议这样做。 "previous"状态未记录。