随机,但只是在Chrome中



我有这个函数来创建随机范围内的数字。

function randomRange(min, max) {
  return (new Array(++max-min))
  .join('.').split('.')
  .map(function(v,i){ return min+i; })
  .sort(function(){ return 0|Math.random()*max; });
}

它完美运行,但仅在Chrome中。由于某种原因,所有其他浏览器几乎没有变化......

我这里有一个简单的演示,所以你可以看到 http://jsfiddle.net/elclanrs/zZRda/区别。

如您所见,Chrome中的数字顺序大多是随机的,但在其他浏览器中没有太大变化,只有少数数字改变了位置,但看起来几乎相同。

现在检查Chrome和其他浏览器中的 http://jsbin.com/iyalax/3/edit,您将非常清楚地看到差异。

知道为什么会这样吗?

编辑:我还有另一个randomRange功能,可以在所有浏览器中正常工作,它只是更长更丑陋,请检查 http://jsbin.com/iyalax/4/edit 以查看差异。

根据 MDN,

array.sort([compareFunction])

如果 compareFunction(a, b) 返回 0,则保持 a 和 b 不变 相互尊重,但相对于所有不同的排序 元素。注意:ECMAscript 标准不保证这一点 行为,因此并非所有浏览器(例如 Mozilla 版本约会 至少回到 2003 年)尊重这一点。

你可以试试

.sort(function(){ return Math.random()*2-1; })

您在这里要做的只是返回一个大于、小于或等于 0 的数字。

这可能是由于资源管理器之间实现了sort()方法。从我到目前为止看到的事实来看,我想也许 Chrome 在进行排序时总是使用不稳定的排序(例如快速排序),而其他人在输入大小较小时使用过时的排序(例如气泡排序)。

起初,输入(最初从new Array(..)创建)已经排序;并且function(){ return 0|Math.random()*max; }将始终返回非负数,这表明a>=b(或a<=b,我不确定)?因此,当我尝试挖掘这个问题时,我发现Chrome和IE(版本9)之间的排序行为是不同的。

在IE中:[1,2,3].sort( function(){return 1} )给出[1,2,3];但在Chrome中,结果是[3,2,1],所以我相信这可能是真正的因素。

因此,作为结论,我想改用.sort(function(){ return (0|Math.random()*max)-max/2; })

问题解决了!我在 Hacker News 上找到了一个非常甜蜜的解决方案,它现在在所有浏览器中都能完美运行:

function randomRange(min, max) {
  return (new Array(++max-min))
  .join('.').split('.')
  .map(function(v,i){ return min+i; })
  .map(function(v) { return [Math.random(), v]; })
  .sort().map(function(v) { return v[1]; });
}

演示:http://jsbin.com/iyalax/9/edit(如果看不到图像,请单击"使用 JS 运行")

最新更新