2

I've this function to create a random range of numbers.

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; });
}

It works perfect but only in Chrome. All other browsers have very little variation for some reason...

I've a simple demo here so you can see the difference http://jsfiddle.net/elclanrs/zZRda/.

As you can see the order of numbers in Chrome is mostly random but in other browsers there's not much variation, only a few numbers change place but it all looks almost the same.

Now check http://jsbin.com/iyalax/3/edit in Chrome and other browsers and you'll see the difference very clearly.

Any ideas why this is happening?

Edit: I've another randomRange function that works fine in all browsers, it's just longer and uglier, check http://jsbin.com/iyalax/4/edit to see the difference.

elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • `As you can see the order of numbers in Chrome is mostly random` How can you see a random order? [Read this if you want to know more about "random".](http://www.random.org/) – Ron van der Heijden Sep 21 '12 at 10:42
  • Check out the second demo and it becomes very clear. The tiles disappear very randomly in Chrome but in Firefox they disappear mostly from bottom to top, no variation...Click "toggle cats" a few times and you'll see the difference. – elclanrs Sep 21 '12 at 10:45
  • In FireFox I see 1x1 pictures. Perhaps this is a html/css bug – Ron van der Heijden Sep 21 '12 at 10:50
  • 1
    Using The sort function for random shuffling is still often subject to much confusion, so be heedful! – Lorenz Lo Sauer Sep 21 '12 at 10:50
  • @Bondye: Make sure to click "Run with JS" at the top right corner. I think that's a problem with jsbin or placekitten, if you press the button the image will show alright. – elclanrs Sep 21 '12 at 10:51
  • @LoSauer: I guess Chrome is the only one that knows how to do it right ... I'll probably have to use my other function which works fine. – elclanrs Sep 21 '12 at 10:53
  • I did a shuffle implementation a while back. Try ```[...].sort( function(a,b){ return .5-Math.random();} ); ``` – Lorenz Lo Sauer Sep 21 '12 at 10:57
  • @LoSauer: That won't work either, the same problem appears. Seems like `sort` might be a bad idea after all... – elclanrs Sep 21 '12 at 11:01

3 Answers3

1

According to MDN,

array.sort([compareFunction])

If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.

You can try

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

All you're trying to do here is to return a number that is either greater, less than or equal to 0.

Mr. 14
  • 9,228
  • 6
  • 37
  • 54
  • +1, I didn't catch that MDN article. This seems to work fine in FF and Chrome but still got some variation issues in Opera, but the code I found on HN seems to do the trick. – elclanrs Sep 21 '12 at 21:46
0

This may due to the implementation of sort() method between explorers. From the fact that I've seen so far, I guess maybe the Chrome always use non-stable sort(e.g quicksort) when do sorting, while the others use stale sort(e.g bubble sort) when the input size is small.

At first, the input(created originally from new Array(..)) is already sorted; and the function(){ return 0|Math.random()*max; } will always return a non-negative, which indicates that a>=b(or a<=b, I am not sure)? So, when I try to dig this out, I find that the sort behavior is different between Chrome and IE(version 9).

In IE: [1,2,3].sort( function(){return 1} ) gives out [1,2,3]; but in Chrome, the result is [3,2,1], so I believe this maybe the real factor.

So, as a conclusion, I would like to use .sort(function(){ return (0|Math.random()*max)-max/2; }) instead.

Marcus
  • 6,701
  • 4
  • 19
  • 28
0

Problem solved! I found a pretty sweet solution at Hacker News, it works perfect in all browsers now:

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]; });
}

Demo: http://jsbin.com/iyalax/9/edit (click "Run with JS" if you can't see the image)

elclanrs
  • 92,861
  • 21
  • 134
  • 171