预测JavaScript的的Math.random种子(Predict the Seed of Ja

2019-07-03 16:23发布

好了,所以我在做如何的随机数的方法的Math.random产生了一些研究。 到目前为止,我了解到,它开始与一个“随机”种子,而且种子插入一些复杂的方程式来生成一个随机数。 如果种子是永远不变的,将结果始终是相同的?

我听说了的Math.random种子通过电流时产生的,是正确的? 他们必须使用当前时间一路下跌到毫秒什么的,因为如果你没有,你会得到同样的结果。

到底是什么种子? 它是时间,如“10:45”或如“10:45 12年11月8日”或一些组合的时间和日期?

我如何才能找到种子,让我可以预测的输出?

我希望能够堵塞这样的:

alert(Math.floor((Math.random()*10)+1));

进入我的地址栏,并能够预测的结果。 那可能吗?

Answer 1:

我看遍了犀牛的源代码 ,以了解他们使用的伪随机函数。 显然,他们退回到Math.random在定义函数的Java标准库 。

对于文档Math.random说:

返回带有正号,大于或等于0.0且小于1.0的双精度值。 返回值是一个(大约)从该范围均匀分布伪随机选择的。

当该方法中,首先调用时,它创建单个新的伪随机数生成器,就好像由表达

new java.util.Random

新的伪随机数生成器之后用于该方法的所有调用,并不能用于其他地方。

这种方法是完全同步的,以允许多个线程正确使用。 但是,如果许多线程需要以极高的速率生成伪随机数,它可能会减少每个线程有它自己的伪随机数生成。

所以,我检查的文件java.util.Random ,发现这个 (默认构造函数):

创建一个新的随机数发生器。 它的种子被初始化为基于当前时间的值:

public Random() { this(System.currentTimeMillis()); }

同一毫秒内创建了两个随机的对象将随机数的顺序相同。

所以,现在我们肯定知道该种子以毫秒为单位的当前时间。 此外,对于文档第二个构造说:

创建使用单个long种子新的随机数生成器:

public Random(long seed) { setSeed(seed); }

通过使用方法旁边持有伪随机数生成器的状态。

该文档为setSeed方法说:

设置此随机数生成器的使用单个long种子的种子。 过setSeed的常规协定是,它改变了这个随机数生成器对象的状态,以便在完全相同的状态,如果它刚刚与争论的种子作为种子创建。 该方法过setSeed由类随机实现如下:

synchronized public void setSeed(long seed) {
    this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
    haveNextNextGaussian = false;
}

由Random类的setSeed实现恰好只使用48给定的种子位。 一般地,然而,压倒一切的方法可以使用long参数的所有64位作为种子值。 注:尽管种子值是一个AtomicLong的,仍必须同步此方法来确保haveNextNextGaussian的语义正确。

的实际方法用于生成随机数为nextDouble

返回下一个伪,均匀地从该随机数生成器的序列分布在0.0和1.0之间的双值。

在实施nextDouble功能如下:

public double nextDouble() {
    return (((long)next(26) << 27) + next(27))
        / (double)(1L << 53);
}

显然,这取决于对next功能:

产生一个伪随机数。 子类应当覆盖这一点,因为这是使用的所有其他方法。

在执行next功能如下:

synchronized protected int next(int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (int)(seed >>> (48 - bits));
}

这就是你正在寻找的伪随机函数。 由于它在文档中据说:

这是一个线性同余伪随机数发生器,由DH莱默所定义并且由Donald E. Knuth的在计算机程序设计,第2卷的技术中说明:半数值算法,第3.2.1节。

但是请注意,这仅是犀牛使用的随机数发生器。 喜欢的SpiderMonkey和V8其他实现可以拥有自己的伪随机数生成器。



Answer 2:

很可能有更多的种子比毫秒计的,因为你可以调用的Math.random()多次在同一毫秒,它会每次都返回不同的值。

for (var i = 0; i < 3; i++) {
    console.log(Math.random(), (new Date()).getTime());
};

我的输出:

0.0617244818713516 1352433709108
0.8024995378218591 1352433709108
0.2409922298975289 1352433709108

如果我实现它,我可能会基于上一毫秒计的初始种子,然后添加各1个,它被称为时间,这样你就不会得到相同的种子值的两倍。

这里的预测从产出的100%准确的方法Math.random()

Math.random = function () { return .5; };

现在Math.random()将始终返回.5



Answer 3:

种子是一个数值,所以我的猜测是,这将是你会得到什么,如果你调用Date.now()new Date().getTime()旧版本浏览器)。

但是,我不知道当种子被占用,或者如果种子被隔离到当前页面或共同到整个浏览器进程。 预测的随机数字应该是很难或不可能的,这是他们被随机整点。



Answer 4:

不,你无法预知的种子,但你可以preemtively为了准确蛮力匹配产生足够的数量。

-总之,通过读取RNG的wiki页面开始的http://en.wikipedia.org/wiki/Random_number_generation ,在看PRNG的实际实现。



文章来源: Predict the Seed of Javascript's Math.random