Consider the following C program :
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
srand(time(NULL));
for (int i = 0; i < 20; ++i) {
static float a = 0;
a = (rand() % 2001 - 1000) / 2.e3;
printf("%.4f ", a);
}
}
This will successfully generate then print a list of random number between -0.5 to 0.5. For example :
./main.out
-0.2475 -0.3640 -0.3945 0.2995 0.0460 0.2230 -0.0340 0.1630 -0.2275 -0.3450 0.3560 -0.4335 -0.0025 -0.2980 -0.0505 -0.1815 0.3115 -0.4465 -0.1325 -0.2340
I checked the Precedence of Operators and still don’t understand how the expression (rand()%2001 - 1000)/2.e3 works.
(especially where does the negative sign comes from)
I hope some could explain this, thank you.
>Solution :
Let’s analyze the expression (rand() % 2001 - 1000) / 2.e3:
-
the
rand()function defined in<stdlib.h>returns a pseudo random integer of typeintin the range0toRAND_MAXinclusively.RAND_MAXis a constant also defined in<stdlib.h>whose value is at least32767. -
rand() % 2001computes the remainder of the division by2001. Sincerand()is positive, the result is a pseudo random number in the range0to2000inclusive, with a small bias caused by2001not dividingRAND_MAXevenly. -
rand() % 2001 - 1000is evaluated as(rand() % 2001) - 1000, the range of the result is shifted by 1000 toward the negatives, namely between-1000and1000inclusively. -
to evaluate
(rand() % 2001 - 1000) / 2.e3, the value obtained from the previous steps is converted to typedoubleand divided by2.e3, which would be more readable as2000.0. Hence the result is a floating point value of typedoublewith 2001 possible distinct values between-0.5and0.5inclusively. -
a = (rand() % 2001 - 1000) / 2.e3;converts thisdoublevalue tofloat, the type ofa. Thefloatvalue will be implicitly converted back to typedoublewhen passed toprintf, this conversion does not produce exactly the same number in many cases. -
note that there is no reason to define
aas astaticvariable.
Here is an alternative implementation that produces more distinct values in the same inclusive range with a slightly less biased distribution:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
for (int i = 0; i < 20; ++i) {
double a = rand() / (double)RAND_MAX - 1.0;
printf("%f ", a);
}
printf("%\n");
return 0;
}