【问题标题】:How to generate random numbers in a very large range via javascript?如何通过javascript生成很大范围内的随机数?
【发布时间】:2014-04-30 15:33:10
【问题描述】:

这个功能我用了很久,很满意。你可能已经看过几百万次了。它甚至在 the example section of the MDN documentation for Math.random()!

function random(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
};

但是,当我在非常大的范围内调用它时,它的表现非常糟糕。以下是一些结果:

for(var i=0;i<100;i++) { console.log(random(0, 34359738368)) }

34064924616
6800671568
30945277424
2591785504
16404206304
29609031808
14821448928
10712020504
26471102024
21454653384
33180253592
28189739360
27189739528
1159593656
24058421888
13727549496
21995862272
20907450968
28767901872
8055552544
2856286816
28137132160
22775692392
21141911808
16418994064
28151646560
19928528408
11100796192
24022825648
17873139800
10310184976
7425284936
27043756016
2521657024
2864339728
8080550424
8812058632
8867252312
18571554760
19600873680
33687248280
14707542936
28864740112
26338252144
7877957776
28207487968
2268429496
14461565136
28062983608
5637084472
29651319832
31910601904
19776200528
16996597392
2478335752
4751145704
24803500872
21899551216
23144535632
19854787112
8490486080
14932659320
8625736560
11379900040
32357265704
33852039680
2826278800
4648275784
27363699728
14164020752
22279817656
25238815424
16569505656
30065335928
9904863008
26944796040
23179908064
19887944032
27944730648
16242926184
6518696400
25727832240
7496221976
19014687568
5685988776
34324757344
12538943128
21639530152
9532790800
25800487608
34329978920
10871183016
23748271688
23826614456
11774681408
667541072
1316689640
4539806456
2323113432
7782744448

几乎没有随机性。所有数字都是偶数。

我的问题是:克服这个问题的规范方法(如果有的话)是什么?我的印象是上述随机函数是范围内随机数的首选函数。提前致谢。

【问题讨论】:

  • 不完全是答案,但尝试使用奇数作为上限。
  • @user1929959:该问题的答案只是说使用上述功能。他们没有解释上述测试的结果,也没有说明如何处理这些影响。
  • 它似乎返回的是随机的 32 位浮点数,而不是 64 位。
  • 我认为这是一个浏览器错误。它在 Firefox 上运行良好,但 Chrome 提供了糟糕的精度。

标签: javascript random largenumber


【解决方案1】:

这很奇怪!好吧,您知道在计算机方面没有真正随机的东西。总有一种算法被使用。所以你找到了一个导致这个特定算法偶数的数字。 我试了一下,不一定是大数造成的。更有可能是数字的某种因式分解。只需尝试另一个数字,如果您愿意,甚至可以更大,您应该得到的输出并不全是偶数。前任。更大的 134359738368 并不是所有的奇数或偶数。

【讨论】:

    【解决方案2】:

    一般的答案是不要使用 Math.random。它完成了工作,但并不是特别好。最重要的是,Javascript 中任何大于 0xffffffffUL 的数字都不是由整数值表示的——它是一个 IEEE 754 值,具有 MDN 网站上注明的行为:“请注意,JavaScript 中的数字是 IEEE 754 浮点数,带有 四舍五入到最近的偶数行为...."

    这就是你所看到的。

    如果您想要更大的随机数,那么您可能需要获取 Mersenne Twister 或 Blum-Blum-Shub 之类的 32 位随机整数值并将它们相乘。这将消除舍入问题。

    【讨论】:

    • 嗨。我很久以前就接受了你的回答,但@user3363398 所说的并没有让我感到平静。正如我正确理解的那样,这是一个精度问题,对吧?我们如何解释这样一个事实:如果我们使用一个不是 2 的幂(但仍大于 2**35)的数字,我们仍然会得到奇数作为结果?在此先感谢您,很抱歉再次打扰您。 :)
    • 无论我们尝试什么,当前形式的 JavaScript 都没有 64 位整数。在某些时候,生成的数字将超过格式中可用的整数位,并且数学引擎将执行其舍入技巧。我查看了 ES6 规范,即使是类型化数组也不会比 32 位无符号数更好地处理。我认为这里的问题是您是否可以使用 32 位限制内的数字。 user3363398 看到的可能只是数学引擎使用的特定算法的变幻莫测。
    • 提供的 random() 函数也不是那么好——与 C 标准库中的函数没有太大区别。如果您可以使用 32 位的实际无符号整数,您将通过选择更好的 PRNG 算法获得更好的结果。不是更快——而是更好。
    【解决方案3】:

    WebCrypto API(所有主要浏览器都在草案中支持)提供加密随机数....

    /* assuming that window.crypto.getRandomValues is available */
    
    var array = new Uint32Array(10);
    window.crypto.getRandomValues(array);
    
    console.log("Your lucky numbers:");
    for (var i = 0; i < array.length; i++) {
        console.log(array[i]);
    }
    

    W3C 标准 https://www.w3.org/TR/WebCryptoAPI/

    这里的例子。 https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues

    【讨论】:

      猜你喜欢
      • 2010-12-24
      • 1970-01-01
      • 2014-05-08
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多