views:

344

answers:

4

I give it 0 and 400 and it returns me sometimes values above 400. That doesn't make sense.

- (float)randomValueBetween:(float)low andValue:(float)high {
    return (((float) arc4random() / RAND_MAX) * (high - low)) + low;
}

that's actually a snippet I found on the net. Maybe someone can see the bug in there?

+6  A: 

The manual page for arc4random indicates that the returned value can be anywhere in the range valid for u int32 (i.e. 0 to (2**32)-1). This means you'll want to divide by 0xFFFFFFFF, instead of RAND_MAX, which I would imagine is less (it is library dependant however, so you'll have to check exactly what it is).

Your function should thus become:

- (float)randomValueBetween:(float)low andValue:(float)high {
    return (((float) arc4random() / 0xFFFFFFFFu) * (high - low)) + low;
}
Noldorin
+5  A: 
  • arc4random returns a pseudo-random value from zero to (2 ^ 32 - 1)
  • RAND_MAX has a default value of (2 ^ 31 - 1)

So the function is probably multiplying the (high - low) range by up to a factor of 2, for random values in the range 0 - 800.

pianoman
+3  A: 

On the iPhone, RAND_MAX is 0x7fffffff (2147483647), while arc4random() will return a maximum value of 0x100000000, so (4294967296) / (2147483647) = 2..... 2 * (400-0) + 0 = 800 ! the max value the method can return

Matthieu
A: 

A simpler variant would be:

- (float)randomValueBetween:(float)low andValue:(float)high {
    return (arc4random() % * (high - low)) + low;
}

Since you're already doing a mod operation why not do it directly on the range of interest?

Also, why are you passing in floats (and returning floats) if you only ever pass in round numbers? Integers are more efficient.

Kendall Helmstetter Gelner