I'm trying to understand a C program which includes a .h file with the line
#define random ((float) rand() / (float)((1 << 31) - 1))
The C program also includes <math.h>
.
My guess is that this simply produces a random number from a uniform distribution on the interval [0,1]; is this correct?
Ostensibly yes. But it's wrong in two principal ways:
Use RAND_MAX
instead. That's what it's there for. It might be much smaller than 1 << 31 - 1
.
1 << 31
will give you undefined behaviour on a platform with a 32 bit int
or less, which is remarkably common. Don't do that!
Note that if you don't want to ever recover the value 1, (as is often the case), then use RAND_MAX + 1.0
on the denominator. The 1.0
forces evaluation in floating point: you run the risk of overflowing an integral type if you write RAND_MAX + 1
.
The rand
function returns a value between 0 and RAND_MAX
. This program is assuming that RAND_MAX
is 2^31 - 1 and is dividing the result by that number.
So yes, if the above assumption is true, then this macro gives a number from [0,1]. It is not so much a uniform random distribution, but rather a "pseudo-random" value.
At least that's what it's supposed to do. This expression (1 << 31)
invokes undefined behavior (assuming int
is 32-bit or less) because the the constant 1
has type int
and left-shifting by 31 puts it outside the range of int
. In practice, if two's complement representation is used, some compilers will allow this shift and then the subsequent -1
will put it back in range, but that can't be depended on.
This undefined behavior can be avoided by using (1U << 31)
, which makes the constant 1
have type unsigned int
so that the shift it within range. A better option is to forget the shift and subtract and just use 0x7fffffff
.
But for maximum portability, it should be defined as follows:
#define random ((float)rand() / RAND_MAX)
But there's still a problem. A float
typically has a 23 bit mantissa. If rand
returns a 32 bit value, you won't get a good distribution of numbers. Better use use double
, which has a 52 bit mantissa:
#define random ((double)rand() / RAND_MAX)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With