Math.random()如何在javascript中工作?

时间:2013-11-20 23:04:23

标签: javascript math

我最近想出了如何通过谷歌获取一个随机数,它让我想到了Math.random()是如何工作的。所以在这里,我无法弄清楚他们是如何做Math.random()的,除非他们使用了类似的时间,有没有人知道JavaScript的Math.random()是如何工作的还是等价的?

5 个答案:

答案 0 :(得分:24)

Math.random()返回一个带有正号的数字值,大于或等于0但小于1,使用依赖于实现的算法或策略随机或伪随机选择,在该范围内具有近似均匀的分布。

这是V8的实施:

uint32_t V8::Random() {

    // Random number generator using George Marsaglia's MWC algorithm.
    static uint32_t hi = 0;
    static uint32_t lo = 0;

    // Initialize seed using the system random(). If one of the seeds
    // should ever become zero again, or if random() returns zero, we
    // avoid getting stuck with zero bits in hi or lo by reinitializing
    // them on demand.
    if (hi == 0) hi = random();
    if (lo == 0) lo = random();

    // Mix the bits.
    hi = 36969 * (hi & 0xFFFF) + (hi >> 16);
    lo = 18273 * (lo & 0xFFFF) + (lo >> 16);
    return (hi << 16) + (lo & 0xFFFF);
}

来源:http://dl.packetstormsecurity.net/papers/general/Google_Chrome_3.0_Beta_Math.random_vulnerability.pdf

以下是StackOverflow上的几个相关主题:

答案 1 :(得分:2)

他们使用“时间之类的东西”是正确的。伪随机生成器通常使用系统时钟进行播种,因为这是一个数字的良好来源并不总是相同。

一旦随机生成器用数字播种,它将生成一系列数字,这些数字都取决于初始值,但是它们看起来是随机的。

一个简单的随机生成器(实际上在编程语言中使用了一段时间)就是在这样的算法中使用素数:

rnd = (rnd * 7919 + 1) & 0xffff;

这会产生一系列来回跳跃的数字,看似随机。例如:

seed = 1337
36408
22089
7208
63833
14360
11881
41480
13689
6648

Javascript中的随机生成器稍微复杂一些(为了给出更好的分布)并使用更大的数字(因为它必须产生一个大约60位而不是16位的数字),但它遵循相同的基本原则

答案 2 :(得分:2)

请参阅:There's Math.random(), and then there's Math.random()

直到最近(版本4.9.40之前),V8选择的PRNG是MWC1616(乘以进位,将两个16位部分组合在一起)。它使用64位内部状态,看起来像这样:

uint32_t state0 = 1;
uint32_t state1 = 2;
uint32_t mwc1616() {
  state0 = 18030 * (state0 & 0xffff) + (state0 >> 16);
  state1 = 30903 * (state1 & 0xffff) + (state1 >> 16);
  return state0 << 16 + (state1 & 0xffff);

然后按照规范将32位值转换为介于0和1之间的浮点数。

MWC1616占用很少的内存,计算速度非常快,但不幸的是,它的质量不及标准

  • 它可以生成的随机值的数量限制为232,因为 相对于0到1之间的252个数字,双精度 浮点数可以表示。
  • 最重要的上半部分 结果几乎完全取决于state0的值。的 周期长度最多为232,而不是几个大 排列周期很多。选择不当 初始状态下,周期长度可以小于4000万。
  • 它无法通过TestU01套件中的许多统计测试。

已经向我们指出了这一点,并且已经理解了问题,并且在进行了一些研究之后,我们决定基于称为xorshift128 +的算法重新实现Math.random。它使用128位内部状态,周期长度为2128-1,并通过了TestU01套件中的所有测试。

uint64_t state0 = 1;
uint64_t state1 = 2;
uint64_t xorshift128plus() {
  uint64_t s1 = state0;
  uint64_t s0 = state1;
  state0 = s0;
  s1 ^= s1 << 23;
  s1 ^= s1 >> 17;
  s1 ^= s0;
  s1 ^= s0 >> 26;
  state1 = s1;
  return state0 + state1;
}

在我们意识到这一问题的几天之内,新的实现就降落在V8 4.9.41.0中。它将在Chrome 49中提供。Firefox和Safari也都切换到了xorshift128 +。

答案 3 :(得分:0)

Data Stg._20181009_Financial - 20180909;

答案 4 :(得分:0)

您可能需要本文作为参考:https://hackernoon.com/how-does-javascripts-math-random-generate-random-numbers-ef0de6a20131

顺便说一句,最近,我也对这个问题感到好奇,然后阅读了NodeJS的源代码。我们可以从Google V8中了解一种可能的实现方式:

随机(MathRandom::RefillCache函数)的主要条目: https://github.com/v8/v8/blob/master/src/math-random.cc

种子如何初始化?另请参见此处:https://github.com/v8/v8/blob/master/src/base/utils/random-number-generator.cc#L31

关键功能是(XorShift128 功能): https://github.com/v8/v8/blob/master/src/base/utils/random-number-generator.h#L119

在此头文件中,有对某些论文的引用:

// See Marsaglia: http://www.jstatsoft.org/v08/i14/paper
// And Vigna: http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf