A float is supposed to be signed, so why is subtraction causing a wrap-around?

objective-c, type-conversion, types

Solution

`arc4random()` returns a `u_int32_t` according to the man page, so `arc4random()%500-500` will be an unsigned integer, and subtracting 500 will give you a very large positive value. Try this instead:

float test = ((float)(arc4random() % 500))-500;

I produced a work-around where I made a signed int, then cast it to a float, but I'd really appreciate knowing how/why this happened.

Look at the entire line one piece at a time. First, you've got:

arc4random()

As I said above, that returns an unsigned int. Let's pretend that it returns the value `12345`. Next, you've got the modulus operator, so your expression is something like:

12345 % 500

which is to say `345`. Next, you subtract 500:

345 - 500

You'd think that'd give you -155, but no -- we're still working in the realm of unsigned ints here, so you really get `4294967141` (or something like that -- my math may be off). Then, finally, you assign that to a float:

float test = 4294967141;

A float only has 23 bits for the mantissa, so the value that's stored in `test` will be in the general neighborhood of 4294967141, but with less precision, like 4294970000.

Problem

``` float test=-1; ``` produces a `float` with value `-1`. However, ``` float test=arc4random()%500-500; ``` produces enormous values that clearly resulted from a buffer overflow -- the numbers wrapping around. This should not happen with a `float`; for kicks, I tried to see if Xcode would let me make a "signed float", but it told me "floats cannot be signed or unsigned." I produced a work-around where I made a signed `int`, then cast it to a `float`, but I'd really appreciate knowing how/why this happened.

Original source