bug#79369: seq generates wrong sequences for big numbers

Pádraig Brady <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Message-ID <[email protected]>
On 02/09/2025 13:11, [email protected] wrote:
> It looks like seq for integers bigger than 2^64 sometimes generate wrong
> results. There are few examples of wrong output I have found:
> 
> 
> $ seq 18446744073709551617 inf | head -3
> 
> 18446744073709551616
> 18446744073709551617
> 18446744073709551618
> 
> 
> 
> 
> 
> $  seq 10000000000000000000000000000 inf | head -3
> 
> 
> 9999999999999999999731564544
> 9999999999999999999731564545
> 9999999999999999999731564546

We can improve for the above 2 cases anyway,
with something like the attached.

Large magnitude negative start values are still problematic.

cheers,
Padraig
seq-large-start.patch (text/x-patch, 2.3 KB)
From bf3c75911d1b50d557960943daaeb20a65f0140f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Tue, 2 Sep 2025 16:35:52 +0100
Subject: [PATCH] seq: be more accurate with large integer start values

* src/seq.c (main): Use seq_fast() with large integer only
start values, by avoiding innacurate conversion to double.
* NEWS: Mention the improvement.
---
 NEWS      | 6 +++++-
 src/seq.c | 8 ++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index dd8c1a4cf..e732e3ddd 100644
--- a/NEWS
+++ b/NEWS
@@ -116,11 +116,15 @@ GNU coreutils NEWS                                    -*- outline -*-
 
   tsort now accepts and ignores -w.
 
-** Performance improvements
+** Improvements
 
   'factor' is now much faster at identifying large prime numbers,
   and significantly faster on composite numbers greater than 2^128.
 
+  'seq' is faster and more accurate with large integer start values.
+  Previously 'seq 18446744073709551617 inf | head -n3' would start
+  with the number before the user specified start value.
+
 ** Build-related
 
   cksum was not compilable by Apple LLVM 10.0.0 x86-64, which
diff --git a/src/seq.c b/src/seq.c
index ea9b7d8a4..59de49798 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -628,6 +628,8 @@ main (int argc, char **argv)
       usage (EXIT_FAILURE);
     }
 
+  char const *user_start = n_args == 1 ? "1" : argv[optind];
+
   /* If the following hold:
      - no format string, [FIXME: relax this, eventually]
      - integer start (or no start)
@@ -648,7 +650,7 @@ main (int argc, char **argv)
                          && all_digits_p (argv[optind + 2])))
       && !equal_width && !format_str && strlen (separator) == 1)
     {
-      char const *s1 = n_args == 1 ? "1" : argv[optind];
+      char const *s1 = user_start;
       char const *s2 = argv[optind + (n_args - 1)];
       seq_fast (s1, s2, step.value);
     }
@@ -683,7 +685,9 @@ main (int argc, char **argv)
     {
       char *s1;
       char *s2;
-      if (asprintf (&s1, "%0.Lf", first.value) < 0)
+      if (all_digits_p (user_start))
+        s1 = xstrdup (user_start);
+      else if (asprintf (&s1, "%0.Lf", first.value) < 0)
         xalloc_die ();
       if (! isfinite (last.value))
         s2 = xstrdup ("inf"); /* Ensure "inf" is used.  */
-- 
2.50.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.