预测Javascript的种子';随机数学

预测Javascript的种子';随机数学,javascript,random,seed,Javascript,Random,Seed,好的,我正在做一些关于如何用Math.random方法生成随机数的研究。到目前为止,我了解到它是从一个“随机”种子开始的,这个种子被插入到一些复杂的方程中,以创建一个随机数。如果种子总是一样的,结果会永远一样吗 我听说Math.random的种子是通过当前时间生成的,对吗?他们必须使用当前时间,一直到毫秒或其他什么,因为如果你不这样做,你会得到同样的结果 种子到底是什么?是“10:45”之类的时间,还是“10:45 11/8/12”之类的时间和日期,还是某种组合 如何找到种子,以便预测产量 我希

好的,我正在做一些关于如何用Math.random方法生成随机数的研究。到目前为止,我了解到它是从一个“随机”种子开始的,这个种子被插入到一些复杂的方程中,以创建一个随机数。如果种子总是一样的,结果会永远一样吗

我听说Math.random的种子是通过当前时间生成的,对吗?他们必须使用当前时间,一直到毫秒或其他什么,因为如果你不这样做,你会得到同样的结果

种子到底是什么?是“10:45”之类的时间,还是“10:45 11/8/12”之类的时间和日期,还是某种组合

如何找到种子,以便预测产量

我希望能够插上插头:

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

进入我的url栏,并能够预测结果。这是可能的吗?

种子是一个数值,所以我猜如果调用
Date.now()
(或者
new Date().getTime()
,对于较旧的浏览器)就会得到它


但是,我不确定何时获取该种子,或者该种子是否与当前页面隔离,或者是否与整个浏览器进程共用。预测随机数被认为是非常困难或不可能的,这就是随机数的全部意义。

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

for (var i = 0; i < 3; i++) {
    console.log(Math.random(), (new Date()).getTime());
};
如果我实现它,我可能会根据毫秒计数生成初始种子,然后每次调用它时添加1,这样就不会两次获得相同的种子值

这里有一种100%准确的方法,可以从
Math.random()
预测输出:


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

不,您无法预测种子,但您可以先发制人地生成足够的数字,以便准确地强制匹配


无论如何,从阅读RNG的wiki页面开始,看看PRNG的实际实现。

我查看了Rhino,以找出它们使用的伪随机函数。显然,它们与中定义的
Math.random
函数有关

Math.random
的文档说明:

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

当第一次调用此方法时,它会创建一个新的伪随机数生成器,就像表达式一样

此后,这个新的伪随机数生成器将用于此方法的所有调用,并且不会在其他任何地方使用

此方法已正确同步,以允许多个线程正确使用。然而,如果许多线程需要以很快的速度生成伪随机数,那么它可以减少每个线程拥有自己的伪随机数生成器的争用

因此,我检查了
java.util.Random
的文档,发现(对于默认构造函数):

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

在同一毫秒内创建的两个随机对象将具有相同的随机数序列

现在我们可以确定种子是以毫秒为单位的当前时间。此外,该文件还说明:

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

用于保持伪随机数生成器状态的方法

setSeed
方法的

使用单个长种子设置此随机数生成器的种子。setSeed的一般约定是,它改变这个随机数生成器对象的状态,使其处于完全相同的状态,就好像它是用参数seed作为种子创建的一样。方法setSeed由Random类实现,如下所示:

public double nextDouble() {
    return (((long)next(26) << 27) + next(27))
        / (double)(1L << 53);
}
synchronized protected int next(int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (int)(seed >>> (48 - bits));
}
显然,在
下一个
功能中:

生成下一个伪随机数。子类应该重写它,因为所有其他方法都使用它

next
功能的实现如下:

public double nextDouble() {
    return (((long)next(26) << 27) + next(27))
        / (double)(1L << 53);
}
synchronized protected int next(int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (int)(seed >>> (48 - bits));
}
synchronized protected int next(整数位){
seed=(seed*0x5deec66dl+0xBL)和((1L>>(48位));
}
这就是您要寻找的伪随机函数。正如文档中所述:

这是一个线性同余伪随机数生成器,由D.H.Lehmer定义,Donald E.Knuth在《计算机编程艺术》第2卷:半数值算法,第3.2.1节中描述


但是请注意,这只是Rhino使用的随机数生成器。其他实现(如Spidermonkey和V8)可能有自己的伪随机数生成器。

Math.random()的全部要点是您无法预测它(至少,不是没有很大的困难).有没有人在这里阅读
v8
的源代码给我们一个明确的答案?@tishuo-我阅读了Rhino的源代码,并根据我读到的内容回答了这个问题:@43.52.4D。有一种方法可以找到答案。开始做吧,十年后我们会得到答案,意思是,如果可能的话……你是真的吗?!这是codChrome数学背后的e.random():看起来它基本上将使用您的系统的随机数生成器,所以它的性能最终取决于您的操作系统的RNG。+1,很好的答案,因此这意味着至少我可以根据时间的准确性列举一系列可能的时间,至少我可以得到一个可能的随机数列表(出于安全原因,这肯定是不安全的)。但是对于最初的问题,可能不是,除非您能够准确地获得毫秒值。@aa如果您正在编写一个webapp u,那么它取决于实现,这是正确的
public Random(long seed) { setSeed(seed); }
synchronized public void setSeed(long seed) {
    this.seed = (seed ^ 0x5DEECE66DL) & ((1L << 48) - 1);
    haveNextNextGaussian = false;
}
public double nextDouble() {
    return (((long)next(26) << 27) + next(27))
        / (double)(1L << 53);
}
synchronized protected int next(int bits) {
    seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
    return (int)(seed >>> (48 - bits));
}