PDA

View Full Version : Can the Math.random() command actually return a 0 or 1?


JoeF
11-02-2002, 09:13 PM
I'm a newby that just finished an online javascript course. When I do a search on Math.random() I receive sites that all describe the command as returning a number 'between 0 and 1'.
My question is - are the expected numbers limited to -
0.0000000000000001 thru 0.9999999999999999
or is it possible to get the 0 and 1 also.
Seems like the definition should be 'from 0 thru 1' rather than 'between 0 and 1'.

JoeF

brothercake
11-02-2002, 09:20 PM
As far as I know, Math.random() will never return exactly 0 or 1, so the decription "between 0 and 1" is accurate

If you want a 0 or 1, then go Math.round(Math.random())

beetle
11-02-2002, 09:25 PM
Hmmm, not sure how conclusive my test is, but I wrote this little script to find out...var count = 0;
var rand = Math.random();
while (rand > 0 && rand < 1) {
document.write(count + " | " + rand +"<br>");
rand = Math.random();
count++
}IE hung up a few times...but I killed it after 457,950 loops. I'd say it's VERY unlikely if not impossible to get a 0 or a 1. So, between seems to be most accurate.

JoeF
11-02-2002, 10:26 PM
Your results seems to be the same as I got. If the number returned has 16 decimal positions, which is what I have mostly seen, the possible numbers would be in the zillions. To actually get a 1.000000000000000 would likely be impossible. Thanks for confirming what I see.

JoeF

beetle
11-03-2002, 12:19 AM
Yes, so unlikely in fact, that according to my calculations, you are ~400 million times more likely to win a state lottery than to retrieve a perfect 1 or 0 with 16 significant digits right of the decimal from Math.random()

With numbers like that, my 500,000 loops are an atom in a water molecule in a drop in the bucket. A BIG bucket :D

ahosang
11-03-2002, 02:48 PM
It returns x, where:
0<=x<1

RadarBob
11-03-2002, 04:49 PM
Simply pick a break point - .5 in this case. A good random number generator makes this a valid technique.

By changing the "breakpoint" you can simulate any ratio you want. For example if you want an even to happen 10% of the time, then breakpoint = .1

Here I've made a javascript object - a coin.


function coin (name, denomination) {
// properties
var this.name = name;
var this.value = denomination;

// methods
this.flipCoin = flipCoin;
}

function flipCoin (theCoin) {
var breakpoint = .5
var sideup = new String();

if (Math.random() <= breakpoint) {
sideup = 'heads';
}else{
sideup = 'tails';
}

return sideup;
} // flipCoin()

var moola = new coin (quarter, .25);
var results = moola.flipCoin;

if (results == 'heads') {
alert (results + " I win!");
}else{
alert ( results + " I loose"
"\n Thats not fair! Its my " + moola.name + " so I always win!!");
}

beetle
11-03-2002, 06:07 PM
Hehe, interesting post, RadarBob. Seriously if you just wanted a 1 or 0 randomly...this is all you need

function getRandBinary() {
return (Math.floor(Math.random() * 9) % 2);
}

SpudMurphy
02-26-2009, 01:04 AM
Your getRandBinary function has been on the internet for 7 years now. :eek: I hope not too many people are using it. Here's why:

This part:
(Math.random() * 9)
is going to give a number in the range [0, 9).

This part:
Math.floor([0, 9))
is going to give a number in the range [0, 8], with all numbers in the range having equal chance.

The final part:
[0, 8] % 2
is going to give a number in the range [0, 1]. However, there are 5 even numbers and only 4 odd numbers. So the chances are 55% and 44% respectively, instead of 50-50.

Use this instead:

function getRandBinary() {
return Math.floor(Math.random() * 2);
}

jkd
02-26-2009, 01:13 AM
Math.random() is supposed to act as though it is distributed uniformly on (0,1). Really, [0,1], (0,1], [0,1), doesn't matter, as it is a beautiful consequence of continuous probability distributions that p(X=x) = 0 for any x. (Of course, nothing on a computer is truly continuous, but even without knowing anything about the internal implementation of Math.random(), I would argue that the probability of Math.random() being 0 or 1 is negligible at worst, 0 at best.

nolliepoper
05-28-2010, 02:03 AM
Use this instead:

function getRandBinary() {
return Math.floor(Math.random() * 2);
}

This is how I roll.
public int getRandBinary()
{
return (int)(Math.random() * 2);
}

randomuser773
05-28-2010, 02:21 AM
Around the time this thread was started, I discovered that Math.random in the then current version of Opera was capable of returning 1 (or a value that tested as 1), with a frequency of about 1 in 35000.
When the first version of Safari for Windows was released, out of curiosity I tested for the same bug and found it to be present. Following my reports both browsers were promptly fixed, but it shows nothing can be taken for granted.

Old Pedant
05-28-2010, 04:02 AM
The *THEORETICAL* way it is supposed to work is simple: A set of 53 random bits are chosen. Therefore, you can have any number ranging from 0.....0 to 1....1 (where there are 53 binary digits, each 0 or 1). That number is then given an exponent, in floating point notation, such that it will be in the range of 0 to 1. (In IEEE floating point, it's legal for a floating point number to *not* be "normalized"...meaning to not have a 1 bit in the uppermost bit position...and then the hardware can and will normalize that value for you.)

HOWEVER... The value can never *BE* 1.00000000000 !!!! Because the only way for that to happen, given the floating point exponent that is applied, would be for there to be 54 bits. But there aren't. There are only 53 bits in the mantissa of an IEEE floating point number.

So...

Yes, 0 is possible. It has one chance in 2^53 of occurring. That's one chance in 9,007,199,254,740,992. In short if you picked one random number ever MICRO-second, you would have a *close* to 100% chance of getting a zero in 6850 YEARS.

But you would have a ZERO chance of ever picking the floating point number 1.000000000000

It constantly amazes me that people express opinions about what a random number generator can and can't do but never bother to go look at the actual implementation, down at the machine code level.

For RandomUser: It would appear that the browsers you noted with the faulty random number algorithm were using only 15 random bits and then stuffing those 15 bits into a floating point number's mantissa. 2^15 is of course 32768, which would mesh with what you saw. If you don't fill up all 53 bits of the mantissa, then of course it's possible to have the floating point number end up as 1.0, depending on where you stuff the (15 in this case) bits into the 53 available. More than likely, they were using some C or C++ library that returned an INT random number and then converting that to floating point. [Might have been 16 bits, depending on how they were doing it.]

Old Pedant
05-28-2010, 04:15 AM
And, finally:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Math/random
Returns a pseudo-random number in the range [0,1) — that is, between 0 (inclusive) and 1 (exclusive)

http://msdn.microsoft.com/en-us/library/41336409(v=VS.85).aspx
The pseudorandom number generated is from 0 (inclusive) to 1 (exclusive)

From http://www.ecma-international.org/publications/

15.8.2.14 random ( )
Returns a number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly
or pseudo randomly with approximately uniform distribution over that range

Even if a person didn't know the implementation, why would they *guess* when the documentation all agrees???

mrhoo
05-28-2010, 09:25 AM
In a test, where a billion random numbers were generated and tested aginst a min and max, Chrome returned zero 12 times, Safari twice, and none of the others came closer than 4.0e-10.

More interestingly, in the billion randoms test(split into ten thousand timered loops of a hundred thousand randoms each) both Safari and Chrome returned the same largest random. 0.9999999990686774.

I would say that you are unlikely to get a 0 from Math.random(), but not unthinkable.
You'll get an infinite number of zeros before you get a 1....

Old Pedant
05-28-2010, 07:19 PM
Which doesn't say much except that Safari and Chrome have incorrectly (or at least poorly) implemented Math.random().

The most interesting part there is that max number: 0.9999999990686774

Look at this code:

<html><body>
<script type = "text/javascript">
var n = 0.5
var s = n
for ( var i = 1; i <= 53; ++i )
{
document.write( i + "::" + s + "<br>" );
n = n / 2;
s = s + n;
}
</script>
done
</body></html>

Observe the value of s when i is 30.

Enough said? We now know that Chrome and Safari are only using 31 bits in creating their random number, instead of the requisite 53. Voila.

(If it's not obvious, the number I am displaying each time is the binary fraction 0.11111111 converted to decimal, where i tells you the number of 1's after the binary point. That is, 0.1 binary is 1/2 or 0.5 decimal. 0.11 binary is 3/4 or 0.75 decimal. etc.)

Old Pedant
05-28-2010, 07:21 PM
By the by, *technically* Chrome and Safari are *NOT* in violation of the ECMAScript specification. Read carefully what it says:

Returns a number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly
or pseudo randomly with approximately uniform distribution over that range

Clearly that is indeed "approximately" uniform. Just more "approximate" than the better implementations.