On changing rand(3) to random(3) in awk(1)
Vitaly Magerya
vmagerya at gmail.com
Thu Aug 28 09:52:04 UTC 2014
On 2014-08-28 09:21, Chenguang Li wrote:
> Since the original rand(3) could not provide a fair, "one-shot" randomness in awk(1),
> I am writing this to suggest that we change *rand(3) to *random(3), which only requires
> modifying a few lines of code[1], but will result in better random number generation.
> BTW, OSX & gawk already have this. Previous discussion can be found here[2].
>
> What do you think?
I think this is a useful change; in particular, srandom(3) seems to do
a much better job of coping with sequential seeds than srand(3), which
solves a big problem with using 'srand' in our awk.
> Index: main.c
> ===================================================================
> --- main.c (revision 270740)
> +++ main.c (working copy)
> @@ -74,7 +74,7 @@
> signal(SIGFPE, fpecatch);
>
> srand_seed = 1;
> - srand(srand_seed);
> + srandom(srand_seed);
>
> yyin = NULL;
> symtab = makesymtab(NSYMTAB/NSYMTAB);
> Index: run.c
> ===================================================================
> --- run.c (revision 270740)
> +++ run.c (working copy)
> @@ -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() % RAND_MAX) / RAND_MAX;
You should not use RAND_MAX with random(3), since it returns values
between 0 and 0x7fffffff (inclusive); RAND_MAX only applies to rand(3).
A better patch would be something like this:
> - /* in principle, rand() returns something in 0..RAND_MAX */
> - u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
> + /* random() returns values in [0, 2147483647] */
> + u = (Awkfloat) random() / 2147483648;
Also, awk(1) man page should be updated; it currently says:
> rand random number on (0,1)
... while it should say:
> rand random number on [0,1)
> break;
> case FSRAND:
> if (isrec(x)) /* no argument provided */
> @@ -1530,7 +1530,7 @@
> else
> u = getfval(x);
> tmp = u;
> - srand((unsigned int) u);
> + srandom((unsigned int) u);
You should probably use 'unsigned long' here.
> u = srand_seed;
> srand_seed = tmp;
> break;
Otherwise, the patch looks fine.
More information about the freebsd-hackers
mailing list