summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2007-06-23 09:27:11 +0200
committerJim Meyering <jim@meyering.net>2007-06-23 09:43:59 +0200
commita0304574e96916f0444b04f301f8e5191615f800 (patch)
tree9613fac65c5f5a4687a67d91212ba0ec4d03676d /src
parent01616c9404b1c66bb395a0438ce28b9e2cb559b7 (diff)
downloadcoreutils-a0304574e96916f0444b04f301f8e5191615f800.tar.xz
seq no longer mishandles cases like "seq 0 0.000001 0.000003",
where it would not print the desired last number. * doc/coreutils.texi (seq invocation): Remove advice about workaround for seq off-by-one problem, since the bug is fixed now. Replace it with more-generic advice about rounding errors. * src/seq.c (long_double_format, print_numbers): New arg NUMERIC_FORMAT. All uses changed.
Diffstat (limited to 'src')
-rw-r--r--src/seq.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/src/seq.c b/src/seq.c
index c59c6b527..d5d5c53a8 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -1,5 +1,5 @@
/* seq - print sequence of numbers to standard output.
- Copyright (C) 1994-2006 Free Software Foundation, Inc.
+ Copyright (C) 1994-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -210,15 +210,53 @@ print_numbers (char const *fmt,
long double first, long double step, long double last)
{
long double i;
+ long double x0 IF_LINT (= 0);
for (i = 0; /* empty */; i++)
{
long double x = first + i * step;
+
if (step < 0 ? x < last : last < x)
- break;
+ {
+ /* If we go one past the end, but that number prints the
+ same way "last" does, and prints differently from the
+ previous number, then print "last". This avoids problems
+ with rounding. For example, with the x86 it causes "seq
+ 0 0.000001 0.000003" to print 0.000003 instead of
+ stopping at 0.000002. */
+
+ if (i)
+ {
+ char *x_str = NULL;
+ char *last_str = NULL;
+ if (asprintf (&x_str, fmt, x) < 0
+ || asprintf (&last_str, fmt, last) < 0)
+ xalloc_die ();
+
+ if (STREQ (x_str, last_str))
+ {
+ char *x0_str = NULL;
+ if (asprintf (&x0_str, fmt, x0) < 0)
+ xalloc_die ();
+ if (!STREQ (x0_str, x_str))
+ {
+ fputs (separator, stdout);
+ fputs (x_str, stdout);
+ }
+ free (x0_str);
+ }
+
+ free (x_str);
+ free (last_str);
+ }
+
+ break;
+ }
+
if (i)
fputs (separator, stdout);
printf (fmt, x);
+ x0 = x;
}
if (i)