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 typeint
in the range0
toRAND_MAX
inclusively.RAND_MAX
is a constant also defined in<stdlib.h>
whose value is at least32767
.rand() % 2001
computes the remainder of the division by2001
. Sincerand()
is positive, the result is a pseudo random number in the range0
to2000
inclusive, with a small bias caused by2001
not dividingRAND_MAX
evenly.rand() % 2001 - 1000
is evaluated as(rand() % 2001) - 1000
, the range of the result is shifted by 1000 toward the negatives, namely between-1000
and1000
inclusively.to evaluate
(rand() % 2001 - 1000) / 2.e3
, the value obtained from the previous steps is converted to typedouble
and divided by2.e3
, which would be more readable as2000.0
. Hence the result is a floating point value of typedouble
with 2001 possible distinct values between-0.5
and0.5
inclusively.a = (rand() % 2001 - 1000) / 2.e3;
converts thisdouble
value tofloat
, the type ofa
. Thefloat
value will be implicitly converted back to typedouble
when passed toprintf
, this conversion does not produce exactly the same number in many cases.note that there is no reason to define
a
as astatic
variable.
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;
}