[Top][All Lists]
[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
- Re: SEQ BUG, (continued)
- Re: SEQ BUG, John Cowan, 2007/06/07
- [PATCH] SEQ BUG, Pádraig Brady, 2007/06/08
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/08
- Re: [PATCH] SEQ BUG, Andreas Schwab, 2007/06/08
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/08
- [PATCH] SEQ BUG,
Pádraig Brady <=
- Re: [PATCH] SEQ BUG, Paul Eggert, 2007/06/13
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/13
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/19
- Re: [PATCH] SEQ BUG, Paul Eggert, 2007/06/19
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/20
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/20
- Re: [PATCH] SEQ BUG, Paul Eggert, 2007/06/22
- Re: [PATCH] SEQ BUG, Pádraig Brady, 2007/06/22
- Re: [PATCH] SEQ BUG, Paul Eggert, 2007/06/22
- Re: [PATCH] SEQ BUG, Jim Meyering, 2007/06/22