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() 01 - 1000)/2.e3 works.
(especially where does the negative sign comes from)
I hope someone could explain this, thank you.
CodePudding user response:
a = (rand() % 2001 - 1000) / 2.e3;
rand() is evaluated first
a = (rand() % 2001 - 1000) / 2.e3;
^^^^^^ int between `0` and `RAND_MAX` inclusive
Then the modulus operator generates a value between 0 and 2000.
a = ([0 .. 2000] - 1000) / 2.e3;
^^^^^^^^^^^ int
Then that value has 1000 subtracted, becoming a value between -1000 and 1000
a = ([-1000 .. 1000]) / 2.e3;
^^^^^^^^^^^^^^^ int
Then, divided by 2000.0 (or 2.e3) generates a double between -0.5 and 0.5
a = [-0.5 .. 0.5];
^^^^^^^^^^^^^ double
CodePudding user response:
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 - 0.5;
printf("%f ", a);
}
printf("%\n");
return 0;
}
