On changing rand(3) to random(3) in awk(1)

Vitaly Magerya vmagerya at gmail.com
Thu Aug 28 16:24:02 UTC 2014


On 08/28/14 16:28, Chenguang Li wrote:
> I am using RANDOM_MAX here to maintain the original code structure.
> I've updated my patch, please check the gist. Thanks!

>  jmp_buf env;
>  extern int     pairstack[];
> @@ -1522,7 +1522,7 @@
>                 break;
>         case FRAND:
>                 /* in principle, rand() returns something in 0..RAND_MAX */
> -               u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
> +               u = (Awkfloat) (random() % RANDOM_MAX) / RANDOM_MAX;
>                 break;
>         case FSRAND:
>                 if (isrec(x))   /* no argument provided */

OK, so this part is wrong (and it is wrong in the original sources
too): this construction generates 0.0 twice as often as it generates
other numbers -- both when random() returns 0 and when it returns
RANDOM_MAX. The correct construction is this:

>         case FRAND:
> -               /* in principle, rand() returns something in 0..RAND_MAX */
> -               u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
> +               /* random() returns values in [0, RANDOM_MAX] */
> +               u = (Awkfloat) random() / (RANDOM_MAX + 1ul);
>                 break;

Note that the "ul" part in "1ul" is vitally important: otherwise there
will be an overflow on systems where long is 32 bit wide. Alternatively
"1.0" can be used here instead.

(Because this overflow may not be obvious in a casual reading, I'm not
a fan of defining RANDOM_MAX separately; I personally would insert the
actual number here directly).


More information about the freebsd-hackers mailing list