From dba1133f9a29a8a8f806a824e884f99136ceb9fc Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 13 Feb 2011 22:20:45 -0800 Subject: [PATCH] Use new Gnulib function dtoastr() to format short, accurate real numbers. %.*g with DBL_DIG + 1 as argument is simple but in rare cases it fails to accurately format a real number. The recently added Gnulib routine dtoastr() always formats a real number accurately, so switch to using it for these cases. --- Smake | 1 + src/data/csv-file-writer.c | 8 +++++--- src/ui/syntax-gen.c | 18 ++++++------------ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Smake b/Smake index 5e05933d..6d54f5b7 100644 --- a/Smake +++ b/Smake @@ -17,6 +17,7 @@ GNULIB_MODULES = \ crypto/md4 \ crypto/md5 \ dirname \ + dtoastr \ environ \ fatal-signal \ fcntl \ diff --git a/src/data/csv-file-writer.c b/src/data/csv-file-writer.c index 70568c3e..11b7429c 100644 --- a/src/data/csv-file-writer.c +++ b/src/data/csv-file-writer.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010, 2011 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 @@ -45,6 +45,8 @@ #include "libpspp/message.h" #include "libpspp/str.h" +#include "gl/ftoastr.h" +#include "gl/minmax.h" #include "gl/unlocked-io.h" #include "gl/xalloc.h" @@ -280,7 +282,7 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv, csv_output_format (w, cv, value); else { - char s[128]; + char s[MAX (DBL_STRLEN_BOUND, 128)]; switch (cv->format.type) { @@ -306,7 +308,7 @@ csv_write_var__ (struct csv_writer *w, const struct csv_var *cv, case FMT_RBHEX: case FMT_WKDAY: case FMT_MONTH: - snprintf (s, sizeof s, "%.*g", DBL_DIG + 1, value->f); + dtoastr (s, sizeof s, 0, 0, value->f); if (w->opts.decimal != '.') { char *cp = strchr (s, '.'); diff --git a/src/ui/syntax-gen.c b/src/ui/syntax-gen.c index 35de44da..9221eae4 100644 --- a/src/ui/syntax-gen.c +++ b/src/ui/syntax-gen.c @@ -30,6 +30,8 @@ #include "libpspp/message.h" #include "libpspp/str.h" +#include "gl/ftoastr.h" + /* Appends to OUTPUT a pair of hex digits for each byte in IN. */ static void syntax_gen_hex_digits (struct string *output, struct substring in) @@ -172,18 +174,10 @@ syntax_gen_number (struct string *output, ds_put_cstr (output, "SYSMIS"); else { - /* FIXME: This should consistently yield precisely the same - value as NUMBER on input, but its results for values - cannot be exactly represented in decimal are ugly: many - of them will have far more decimal digits than are - needed. The free-format floating point output routine - from Steele and White, "How to Print Floating-Point - Numbers Accurately" is really what we want. The MPFR - library has an implementation of this, or equivalent - functionality, in its mpfr_strtofr routine, but it would - not be nice to make PSPP depend on this. Probably, we - should implement something equivalent to it. */ - ds_put_format (output, "%.*g", DBL_DIG + 1, number); + char s[DBL_BUFSIZE_BOUND]; + + dtoastr (s, sizeof s, 0, 0, number); + ds_put_cstr (output, s); } } -- 2.30.2