I see two options apart from reverting my commit.

1. Just fix the bug Otto noticed. Remove the section on randomness
   completely and fix one example in the manual. That's what the patch
   in this mail does. The patch for jot.c is the same as in my previous
   mail.

2. Restore the previous behavior when -w or -c is specified together
   with -r and fix the bug Otto noticed. I will send this patch in a
   second mail.

sobrado@ and I checked that this patch would match the behavior of Linux
and NetBSD. In particular, the format string does not change the output
drastically:

$ jot -r 100000 1 3 | sort -n | uniq -c
33148 1
33452 2
33400 3
$ jot -w %d -r 100000 1 3 | sort -n | uniq -c
33373 1
33239 2
33388 3

I think this behavior makes sense: if the output consists of integers
anyway, then a %d format should not alter it, independently of what
happens under the hood.

The downside is that it breaks scripts that relied on the previous
behavior that was explicitly mentioned in the manual (as Philippe found
the hard way; sorry about that!).

Index: jot.1
===================================================================
RCS file: /var/cvs/src/usr.bin/jot/jot.1,v
retrieving revision 1.19
diff -u -p -r1.19 jot.1
--- jot.1       4 Jan 2016 23:21:28 -0000       1.19
+++ jot.1       16 Jul 2016 19:09:59 -0000
@@ -225,41 +225,6 @@ specifying an integer format:
 .Bd -literal -offset indent
 $ jot -w %d 6 1 10 0.5
 .Ed
-.Pp
-For random sequences, the output format also influences the range
-and distribution of the generated numbers:
-.Bd -literal -offset indent
-$ jot -r 100000 1 3 | sort -n | uniq -c
-24950 1
-50038 2
-25012 3
-.Ed
-.Pp
-The values at the beginning and end of the interval
-are generated less frequently than the other values.
-There are several ways to solve this problem and generate evenly distributed
-integers:
-.Bd -literal -offset indent
-$ jot -r -p 0 100000 0.5 3.5 | sort -n | uniq -c
-33374 1
-33363 2
-33263 3
-
-$ jot -w %d -r 100000 1 4 | sort -n | uniq -c
-33306 1
-33473 2
-33221 3
-.Ed
-.Pp
-Note that with random sequences, all numbers generated will
-be smaller than the upper bound.
-The largest value generated will be a tiny bit smaller than
-the upper bound.
-For floating point formats, the value is rounded as described
-before being printed.
-For integer formats, the highest value printed will be one less
-than the requested upper bound, because the generated value will
-be truncated.
 .Sh EXAMPLES
 Print 21 evenly spaced numbers increasing from \-1 to 1:
 .Pp
@@ -280,7 +245,7 @@ comes after the character
 .Sq z
 in the ASCII character set):
 .Pp
-.Dl "$ jot \-r \-c 160 a { | rs \-g0 0 8"
+.Dl "$ jot \-r \-c 160 a z | rs \-g0 0 8"
 .Pp
 Infinitely many
 .Xr yes 1 Ns 's
Index: jot.c
===================================================================
RCS file: /var/cvs/src/usr.bin/jot/jot.c,v
retrieving revision 1.27
diff -u -p -r1.27 jot.c
--- jot.c       10 Jan 2016 01:15:52 -0000      1.27
+++ jot.c       16 Jul 2016 19:10:18 -0000
@@ -277,9 +277,6 @@ main(int argc, char *argv[])
                if (prec > 9)   /* pow(10, prec) > UINT32_MAX */
                        errx(1, "requested precision too large");
 
-               while (prec-- > 0)
-                       pow10 *= 10;
-
                if (ender < begin) {
                        x = begin;
                        begin = ender;
@@ -287,16 +284,22 @@ main(int argc, char *argv[])
                }
                x = ender - begin;
 
-               /*
-                * If pow10 * (ender - begin) is an integer, use
-                * arc4random_uniform().
-                */
-               use_unif = fmod(pow10 * (ender - begin), 1) == 0;
-               if (use_unif) {
-                       uintx = pow10 * (ender - begin);
-                       if (uintx >= UINT32_MAX)
-                               errx(1, "requested range too large");
-                       uintx++;
+               if (prec == 0 && (fmod(ender, 1) != 0 || fmod(begin, 1) != 0))
+                       use_unif = 0;
+               else {
+                       while (prec-- > 0)
+                               pow10 *= 10;
+                       /*
+                        * If pow10 * (ender - begin) is an integer, use
+                        * arc4random_uniform().
+                        */
+                       use_unif = fmod(pow10 * (ender - begin), 1) == 0;
+                       if (use_unif) {
+                               uintx = pow10 * (ender - begin);
+                               if (uintx >= UINT32_MAX)
+                                       errx(1, "requested range too large");
+                               uintx++;
+                       }
                }
 
                for (i = 1; i <= reps || infinity; i++) {

Reply via email to