Blank project. Code:
int i = 0;
while (i < 8) {
float amount = 100-arc4random_uniform(200);
NSLog(@"amount: %f", amount);
i++;
}
Log:
amount: 21.000000
amount: 90.000000
amount: 79.000000
amount: 4294967296.000000
amount: 39.000000
amount: 4294967296.000000
amount: 81.000000
amount: 4294967296.000000
4294967296.000000 is clearly outside the range of 100 - ran(200)
(pseudocode)
If I don't declare amount
as float
and instead use int
this doesn't happen.
What's going on here?
As @rob points out, arc4random_uniform
returns a 32-bit unsigned integer type (uint32_t
), that is, a number greater than or equal to zero, never negative. The compiler thus evaluates the expression 100-arc4random_uniform(200)
expecting the result also to be an unsigned number.
If the result of arc4random_uniform(200)
in your example code happens to be greater than 100, then 100-arc4random_uniform(200)
will result in a negative number being assigned to a data type that cannot express negative numbers, so you'll end up with unexpected results.
You can indicate to the compiler that you want to be dealing with signed numbers by, as @rob suggests, casting the result of arc4random_uniform
to a signed number (in this case a float
):
float amount = 100 - (float)arc4random_uniform(200);
...or by indicating that the expression should return a signed number by explicitly making your other argument a signed number:
float amount = 100.0f - arc4random_uniform(200);