bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] SEQ BUG


From: Pádraig Brady
Subject: [PATCH] SEQ BUG
Date: Wed, 13 Jun 2007 09:50:39 +0100
User-agent: Thunderbird 1.5.0.8 (X11/20061116)

This patch makes `seq 0.1 0.1 0.9` output 0.1 to 0.9 inclusive, as expected.
The documentation for the previously required workaround is removed.

Note I changed the Makefile for seq to link $(SEQ_LIBM) rather than $(POW_LIB),
as $(POW_LIB) was empty. Is the configure test correct for pow()? as gcc 4.1.2
at least only uses the builtin one when the arguments to pow are positive 
constants.

cheers,
Pádraig.
diff -Naur coreutils/doc/coreutils.texi coreutils.pb/doc/coreutils.texi
--- coreutils/doc/coreutils.texi        2007-06-12 07:28:45.000000000 +0000
+++ coreutils.pb/doc/coreutils.texi     2007-06-12 07:42:01.000000000 +0000
@@ -14041,35 +14041,6 @@
 18446744073709551618
 @end example
 
-Be careful when using @command{seq} with a fractional @var{increment};
-otherwise you may see surprising results.  Most people would expect to
-see @code{0.000003} printed as the last number in this example:
-
address@hidden
-$ seq -s ' ' 0 0.000001 0.000003
-0.000000 0.000001 0.000002
address@hidden example
-
-But that doesn't happen on many systems because @command{seq} is
-implemented using binary floating point arithmetic (via the C
address@hidden double} type)---which means decimal fractions like 
@code{0.000001}
-cannot be represented exactly.  That in turn means some nonintuitive
-conditions like @address@hidden * 3 > 0.000003}} will end up being true.
-
-To work around that in the above example, use a slightly larger number as
-the @var{last} value:
-
address@hidden
-$ seq -s ' ' 0 0.000001 0.0000031
-0.000000 0.000001 0.000002 0.000003
address@hidden example
-
-In general, when using an @var{increment} with a fractional part, where
-(@var{last} - @var{first}) / @var{increment} is (mathematically) a whole
-number, specify a slightly larger (or smaller, if @var{increment} is negative)
-value for @var{last} to ensure that @var{last} is the final value printed
-by seq.
-
 @exitstatus
 
 
diff -Naur coreutils/src/Makefile.am coreutils.pb/src/Makefile.am
--- coreutils/src/Makefile.am   2007-06-12 07:26:01.000000000 +0000
+++ coreutils.pb/src/Makefile.am        2007-06-12 06:43:29.000000000 +0000
@@ -97,7 +97,7 @@
 printf_LDADD = $(LDADD) $(POW_LIB) $(LIBICONV)
 
 # If necessary, add -lm to resolve use of pow in lib/strtod.c.
-seq_LDADD = $(LDADD) $(POW_LIB)
+seq_LDADD = $(LDADD) $(SEQ_LIBM)
 
 # If necessary, add libraries to resolve the `pow' reference in lib/strtod.c
 # and the `nanosleep' reference in lib/xnanosleep.c.
diff -Naur coreutils/src/seq.c coreutils.pb/src/seq.c
--- coreutils/src/seq.c 2007-06-11 10:20:57.000000000 +0000
+++ coreutils.pb/src/seq.c      2007-06-13 07:13:50.000000000 +0000
@@ -21,6 +21,7 @@
 #include <getopt.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <math.h>
 
 #include "system.h"
 #include "c-strtod.h"
@@ -225,6 +226,22 @@
     fputs (terminator, stdout);
 }
 
+/* Calculate adjustment to last value so that inexactness
+   in floating point representation is not significant
+   when comparing against the last value */
+static long double
+get_last_adjustment (operand first, operand step, operand last)
+{
+  int prec = MAX (first.precision, step.precision);
+  prec = MAX (prec, last.precision);
+  if (prec)
+    {
+      long double margin = powl(10,-prec)/2;
+      return (step.value>=0?margin:-margin);
+    }
+  return 0; /* Integers can be exactly represented, so don't adjust */
+}
+
 /* Return the default format given FIRST, STEP, and LAST.  */
 static char const *
 get_default_format (operand first, operand step, operand last)
@@ -359,6 +376,8 @@
        }
     }
 
+  last.value += get_last_adjustment (first, step, last);
+
   if (format_str != NULL && equal_width)
     {
       error (0, 0, _("\
diff -Naur coreutils/tests/seq/basic coreutils.pb/tests/seq/basic
--- coreutils/tests/seq/basic   2007-06-13 07:05:33.000000000 +0000
+++ coreutils.pb/tests/seq/basic        2007-06-13 07:02:29.000000000 +0000
@@ -49,6 +49,11 @@
    ['neg-3',   qw(1 -1 0),     {OUT => [qw(1 0)]}],
    ['neg-4',   qw(1 -1 -1),    {OUT => [qw(1 0 -1)]}],
 
+   ['float-1', qw(0.8 0.1 0.9),        {OUT => [qw(0.8 0.9)]}],
+   ['float-2', qw(0.1 0.99 1.99),      {OUT => [qw(0.10 1.09)]}],
+   ['float-3', qw(10.8 0.1 10.95),     {OUT => [qw(10.8 10.9)]}],
+   ['float-4', qw(0.1 -0.1 -0.2),      {OUT => [qw(0.1 0.0 -0.1 -0.2)]}],
+
    ['eq-wid-1',        qw(-w 1 -1 -1), {OUT => [qw(01 00 -1)]}],
 
    # Prior to 2.0g, this test would fail on e.g., HPUX systems

reply via email to

[Prev in Thread] Current Thread [Next in Thread]