> 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++) {