diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2013-10-16 05:27:11 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2013-10-16 05:27:11 +0300 |
commit | a7fd49bcce48fdda13d635d9b6f946c11abae35b (patch) | |
tree | cdffb2bf3d08b908af16a78d8396f00674243016 | |
parent | e5e28035e44080acb1bf5369ad047d08c7bc9509 (diff) | |
download | egawk-a7fd49bcce48fdda13d635d9b6f946c11abae35b.tar.gz egawk-a7fd49bcce48fdda13d635d9b6f946c11abae35b.tar.bz2 egawk-a7fd49bcce48fdda13d635d9b6f946c11abae35b.zip |
Minor fix in do_rand().
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | builtin.c | 35 |
2 files changed, 40 insertions, 0 deletions
@@ -2,6 +2,11 @@ * re.c (resetup): Add a comment about the joy of syntax bits. + Unrelated: + + * builtin.c (do_rand): If result is exactly 1.0, keep trying. + Thanks to Nelson Beebe. + 2013-10-10 Arnold D. Robbins <arnold@skeeve.com> * dfa.c (lex): Sync with GNU grep. Handle multibyte \s and \S. @@ -2399,9 +2399,44 @@ do_rand(int nargs ATTRIBUTE_UNUSED) * The add/subtract 0.5 keeps small bits from filling * below 2^-53 in the double, not that anyone should be * looking down there. + * + * Date: Wed, 25 Sep 2013 10:45:38 -0600 (MDT) + * From: "Nelson H. F. Beebe" <beebe@math.utah.edu> + * (4) The code is typical of many published fragments for converting + * from integer to floating-point, and I discuss the serious pitfalls + * in my book, because it leads to platform-dependent behavior at the + * end points of the interval [0,1] + * + * (5) the documentation in the gawk info node says + * + * `rand()' + * Return a random number. The values of `rand()' are uniformly + * distributed between zero and one. The value could be zero but is + * never one.(1) + * + * The division by RAND_DIVISOR may not guarantee that 1.0 is never + * returned: the programmer forgot the platform-dependent issue of + * rounding. + * + * For points 4 and 5, the safe way is a loop: + * + * double + * rand(void) // return value in [0.0, 1.0) + * { + * value = internal_rand(); + * + * while (value == 1.0) + * value = internal_rand(); + * + * return (value); + * } */ tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + + while (tmprand == 1.0) + tmprand = 0.5 + ( (random()/RAND_DIVISOR + random()) / RAND_DIVISOR); + return make_number((AWKNUM) (tmprand - 0.5)); } |