1

i have

for (int i = 0; i< 10; i++) {
    CGFloat longerA = ((arc4random() % 80) - 40) / 100.0f;
    NSLog(@"%f",longerA);
}

and the result is

2013-09-20 11:41:30.801 ****[7025:a0b] 0.390000
2013-09-20 11:41:30.801 ****[7025:a0b] 0.080000
2013-09-20 11:41:30.801 ****[7025:a0b] 0.380000
2013-09-20 11:41:30.801 ****[7025:a0b] 42949672.000000
2013-09-20 11:41:30.802 ****[7025:a0b] 0.060000
2013-09-20 11:41:30.802 ****[7025:a0b] 0.080000
2013-09-20 11:41:30.802 ****[7025:a0b] 0.290000
2013-09-20 11:41:30.802 ****[7025:a0b] 42949672.000000
2013-09-20 11:41:30.803 ****[7025:a0b] 0.350000
2013-09-20 11:41:30.803 ****[7025:a0b] 0.180000

i just cant understand why there are results 42949672.000000

Please explain me why this is happening

As i "understand" It must take random(80) - 40 and result / 100.0f so i just don't understand how this (arc4random() % 80) can be more then 79.

zoul
  • 102,279
  • 44
  • 260
  • 354

2 Answers2

2

arc4random returns unsigned integers, which can not be below 0. Subtracting 40 will underflow and wrap around to something close to the maximum value.

You also have modulo bias in your function (some values will be more common than others). Correct for this by using arc4random_uniform(80) instead of doing % 80. Thus the correct solution is:

for (int i = 0; i< 10; i++) {
    CGFloat longerA = (((int)arc4random_uniform(80)) - 40) / 100.0f;
    NSLog(@"%f",longerA);
}
Community
  • 1
  • 1
Hampus Nilsson
  • 6,692
  • 1
  • 25
  • 29
  • Thank you for the answer but i don't like to use casts. Also i already remake this line like CGFloat longerA = (arc4random() % 80) / 100.0f - 0.4f; – Some_single_man Sep 20 '13 at 09:15
  • Then you still retain the modulo bias. The values between 0 and 16 will be twice as comman as 17-79. Use arc4random_uniform instead of % 80. – Hampus Nilsson Sep 20 '13 at 09:24
  • I have read modulo bias. But why 0 - 16 will be twice as comman as 17-79? As i understand i will have some numbers that will have not 1/80 but 1/80 + some_really_small_value. Max rand in u_int32_t is kinda big . But yes you are right i must avoid this low possibility too. – Some_single_man Sep 20 '13 at 09:35
0

The arc4random function is documented to return and u_int32_t. That sounds like an unsigned type, so that when you roll a number < 40 and then subtract 40, you get an arithmetic underflow. That’s where the big number comes from (2^32 – something).

zoul
  • 102,279
  • 44
  • 260
  • 354