JavaScript中更好的随机函数

JavaScript中更好的随机函数,javascript,math,random,Javascript,Math,Random,我目前正在用JavaScript制作康威的生命再现游戏,我注意到函数Math.random()总是返回特定的模式。以下是100x100网格中的随机结果样本: 有人知道如何获得更好的随机数吗? ApplyRandom: function() { var $this = Evolution; var total = $this.Settings.grid_x * $this.Settings.grid_y; var range = parseInt(total * ($

我目前正在用JavaScript制作康威的生命再现游戏,我注意到函数Math.random()总是返回特定的模式。以下是100x100网格中的随机结果样本:

有人知道如何获得更好的随机数吗?

ApplyRandom: function() {

    var $this = Evolution;

    var total = $this.Settings.grid_x * $this.Settings.grid_y;
    var range = parseInt(total * ($this.Settings.randomPercentage / 100));

    for(var i = 0; i < total; i++) {
      $this.Infos.grid[i] = false;
    }

    for(var i = 0; i < range; i++) {
      var random = Math.floor((Math.random() * total) + 1);
      $this.Infos.grid[random] = true;
    }

    $this.PrintGrid();
  },
ApplyRandom:function(){
var$this=进化;
var total=$this.Settings.grid_x*$this.Settings.grid_y;
var range=parseInt(总计*($this.Settings.randomPercentage/100));
对于(变量i=0;i
[更新]

我在这里创建了一个JSFIDLE:

[更新]

看来Math.random()毕竟还可以(谢谢raina77ow)。对不起,伙计们(.如果您对结果感兴趣,下面是游戏的更新版本:

(但我认为还剩下一些bug…

你可以试试

  • (BSD许可证)。它应该有一个好的随机数生成器。请参阅使用示例
  • (BSD或GPL许可证)。有关随机数,请参阅

有关
Math.random()
强度的讨论,请参阅。

Math.random是一种伪随机方法,这就是为什么会得到这些结果。我经常使用的一个旁路是捕捉鼠标光标位置,以便在数学中添加一些盐。随机结果:

Math.random=(function(rand) {
  var salt=0;
  document.addEventListener('mousemove',function(event) {
    salt=event.pageX*event.pageY;
    });
return function() { return (rand()+(1/(1+salt)))%1; };
})(Math.random);

它不是完全随机的,而是更大一点;)

更好的解决方案可能不是随机选取点并将其涂成黑色,而是遍历每一个点,确定填充的几率,然后相应地填充。(也就是说,如果你想让它平均有20%的概率被填充,那么生成你的随机数
r
,并在
r<0.2
时填充,我在WebGL中看到了一个生活模拟器,这就是它初始化…IIRC所做的

编辑:这是另一个考虑绘画方法的原因。随机选择像素可能会导致较少的工作和更少的随机数生成器的调用,这可能是一件好事,这取决于你想要什么。如果您一直跟踪正在填充的像素,并选择填充另一个像素(如果其中一个像素已填充),则基本上您所做的就是在白色像素中随机移动黑色像素的确切百分比。按我的方式操作,所选像素的百分比将遵循二项分布。有时填充的百分比会有点小更多,有时更少。所有洗牌的集合是这种挑选产生的可能性的一个严格子集(严格来说,它也包含了所有画棋盘的可能性,只是获得大多数可能性的几率非常低)简单地说,随机选择每个像素将允许更多的差异


然后,我可以修改洗牌算法,根据二项式概率分布函数生成的数字选择像素百分比,该函数具有定义的期望值/平均值,而不是期望值/平均值本身。老实说,我不知道这会有什么不同——至少在理论上——比为每个像素计算赔率具有期望值/平均值本身的像素。可以做的事情很多。

数学的实现。随机
可能基于a,其一个缺点是随机数取决于早期的值,根据算法中常数的选择产生类似这样的可预测模式。一个著名的示例从中可以看出,常数选择不当的影响

随机数生成器没有这个缺点。您可以在JavaScript中找到MT的实现,例如:


更新:看到您的代码,您在呈现网格的代码中有问题。此行:

var position = (y * 10) + x;
应该是:

var position = (y * grid_x) + x;

使用此修复程序时,没有可识别的模式。

代码中的这一行

var position = (y * 10) + x;
…是导致这种“非随机性”的原因。它真的应该是

var position = (y * $this.Settings.grid_x) + x;
我想
10
是这个网格的原始大小,这就是为什么它在这里。但这显然是错误的:你应该根据网格的当前大小选择你的位置


作为旁注,没有冒犯,但我仍然认为在@ Jayc中给出的算法优于你的算法,而且很容易实现,只需在Apple Youth函数中将两个循环改为一个:

var bias = $this.Settings.randomPercentage / 100;
for (var i = 0; i < total; i++) {
  $this.Infos.grid[i] = Math.random() < bias;
}
var bias=$this.Settings.randomPercentage/100;
对于(变量i=0;i

通过此更改,您将不再受到重复使用
var random=Math.floor((Math.random()*total)+1);
行中相同数字的副作用,这降低了原始代码中的实际单元格填充率。

您可以使用时间戳中的sha256哈希部分,包括纳秒:

console.log(window.performance.now()); //return nanoseconds inside
可以将其编码为字符串, 然后您可以使用以下命令获取哈希:

salt=parseInt(sha256(前一个salt字符串)。子字符串(0,12,16);
//48位数字<2^53-1
然后,使用@nfroidure中的函数, 之前写gen_salt函数,在那里使用sha256散列, 并将gen_salt调用写入eventListener。
你可以使用sha256(上一个字母)+鼠标坐标作为字符串来获得随机散列。

你能给我们看一些代码@Danny吗?相关:Upvoted@Dogbert,看起来确实像一个XY问题。Math.random()本身就是非常随机的。它的结果可能是可以预测的(如论文所示),但它肯定没有遵循此处所示的清晰模式。还有一些错误。事实上,我冒昧地创建了这样一个.Math.random(),正如预期的那样,给出了一个相当混乱的模式。我甚至没有
salt = parseInt(sha256(previous_salt_string).substring(0, 12), 16);
//48 bits number < 2^53-1