views:

380

answers:

11

I'm guessing that most built in random generators return something like this:

[0.0, 1.0)

so if I would like a 50% chance would I use something like this:

if random() < .5

or something like:

if random() <= .5

Thanks for the help.

A: 

It doesn't matter. Both formulas yield the desired result.

Incorrect. The distribution points are on the two sides of the .4(9)-.5 boundary. The <=.5 formula gives slightly better chance to the left distribution point. How much better that chance is depends on the comparison precision.
Franci Penov
Come on! For all practical purposes, the difference between two formulas is negligible.
*All* practical purposes?! Perhaps, unless you have the insane requirement to give 2 things a 50:50 chance of happening, and not 40:60.
Robert Grant
It depends on the precision - if you are generating numbers that are 0.x then it would give 40:60, but if you are generating 0.xyzabcfghjkltyuqwertyuip then it would approximate towards 50:50.
ck
Why is this answer downvoted? From the perspective of *mathematical beauty* only, you are looking at splitting [0, 1) into [0, 0.5) and [0.5, 1). In the case of the real numbers, it doesn't matter which comparison you use because the probability of choosing exactly 0.5 is exactly zero. In the case of floating-point or double-precision numbers in computers, if you are using 'random', then that means you don't need cryptographically strong bits, so the approximation of your chosen datatype to the real numbers is far more than good enough so that it doesn't matter which comparison you pick.
Justice
+4  A: 

To a first approximation, either works.

The best way is to choose a random generator that specifically emits booleans or integers with range. Then you can nail the range exactly.

Operations like "equality" with floating point is iffy anyway.

Jason Cohen
do you know of anything in python that returns a random boolean?
Casey
For Python, consider using a "real" library for random number generators. For example: http://docs.python.org/library/random.html
Jason Cohen
That is, if this level of accuracy is important to you, you ought to use a real library, not the built-in stuff.
Jason Cohen
@Casey: You could use:random.choice((True, False))Also see the randint and randrange functions in that module.
Anon
+3  A: 
 if random() < .5

In binary, .5 is .10000000000.... So, basically, the question reduces to, "What is the first binary digit after the radix point... 0 (for <.5) or 1 (for .5 or more) ?"

James Curran
You're making assumptions about the floating-point representation. Are you assuming it's fixed-point? Cause your description of the representation isn't correct e.g. for Java or C#.
Jason Cohen
Who said anything about data representation? In binary, one half is "0.10000...." in precisely the way it is "0.5" in decimal and "0.8" in hexadecimal. How one chooses to store that in bytes is irrelevant here.
James Curran
OIC, OK I get it, cool.
Jason Cohen
+1 for non-base-10 representation of floating points :-)
Ben Blank
Congradulations! You proved you went to school
joshhunt
Making a genuinely uniform distribution in a float is tricky. There are a lot more representable numbers in the range [0-.5] than in [.5-1], so numbers in the upper area tend to clump together. It's a subtle difference, to be sure.
Nosredna
A: 
< .5

but that assumes that your floating point support is good enough to satisfy your precision demands (since it's never exactly).

Hank Gay
Actually, one half CAN be exactly represented in binary.
James Curran
That's no guarantee that it *is*, though. Depending on what sorts of math got done on the number, it may have gotten rounded to something like .499999999999999
Hank Gay
What maths? We talking about the ability of a compiler to correctly translate the string ".5" into a binary value. If it can't do that, the compiler is hopelessly broken. Why would you trust it to convert "123" into an integer binary value?
James Curran
I was thinking of .5 as a placeholder, although that may not have been warranted.
Hank Gay
A: 

If I want 50% chance, I'd just check for the LSB (Least Significant Bit).

Brian Knoblauch
Bad suggestion, because LSBs can be lousy in many PRNGs. Pick the MSB instead.
starblue
Interestingly enough, I've seen the MSB bit being a bad choice, but haven't seen LSB to be a bad choice yet. However, I can certainly see it happening! Maybe even/odd would be better? :-)
Brian Knoblauch
+8  A: 

Ah, the old ".5" problem. Here's the answer:

If you're going to divide 10 things into two equal parts, you need 5 things in each part. 0 thru 4 in the first part, 5-9 in the second part. So... < .5 is correct.

dwc
+1  A: 

For a particular system you should test it, if you really want to find out. Could take a while though :-)

I agree with the other posters that to the first order, it doesn't matter. If it does matter, you'll need a better RNG anyway.

EDIT: I just tried the default RNG in C# with 1,000,000,000 attempts and the answers were identical...

Mark Pattison
I'm guessing the the "could take a while" is the reason many people come to stack overflow instead of trying to determine things empirically!
Albert
A: 

If you need truly random numbers, you can try random.org. They offer a web service connected to a device that detects noise coming from the universe. Still not random technically speaking, but close enough I guess.

They have all sort of way to make the query such as black and white images.

Coincoin
A: 

If you're going to be that fussy about your random numbers, don't rely on anything that comes built-in. Get a well-documented RNG from a place you trust (I trust Boost, for what that's worth), and read the documentation. It used to be that standard RNGs were notoriously bad, and I still wouldn't trust them.

Alternately, use an integer RNG that gives you discrete values within a range, and divide the range in half. RNGs, in my experience, are integral, and the floating-point function simply divides by the top of the range.

Of course, if this is true, you've got your answer. If the integer RNG produces 0, 1, 2, and 3, the floating-point equivalent will be 0.0, 0.25, 0.5, and 0.75, so the answer is to test < 0.5.

If the RNG isn't based on integral calculations, then it's based on floating-point calculations, and hence is inexact. In that case, it doesn't matter whether you test <= or <, since there is no guarantee that a calculation that should be a precise 0.5 will be.

So, the answer is probably to test < 0.5, which will likely be the correct one if it makes a difference.

David Thornley
+1  A: 

Why do it yourself? Python has random.choice :)

random.choice([0, 1]) will give you 0/1 with equal chances -- and it is a standard part of Python, coded up by the same people who wrote random.random (and thus know more about its semantics than anyone else)

moshez
+1  A: 
import random
def fifty_fifty():
    "Return 0 or 1 with 50% chance for each"
    return random.randrange(2)
ΤΖΩΤΖΙΟΥ