> The second exmaple:
> 
> $ jot -r -p 0 100000 0.5 3.5 | sort -n | uniq -c
> 25120 0
> 49882 2
> 24998 4
> 
> So I'd says there are real bugs introduced with the latest commit.
> 
>       -Otto
> 

Indeed, this is bad. The following patch lets the code fall back to the
old version in the cases that the new code doesn't handle well:

As we discussed on icb, if -p 0 is given, only use the new code if both
endpoints are integers seems to work nicely.

$ jot -r -p 0 100000 0.5 3.5 | sort -n | uniq -c
33434 1
33228 2
33338 3
$ jot -r -p 0 100000 1 3 | sort -n | uniq -c
33464 1
33246 2
33290 3

Bad bias in some cases is unavoidable:

$ jot -r -p 0 100000 1 3.5 | sort -n | uniq -c
19923 1
39934 2
40143 3

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       15 Jul 2016 06:26:29 -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