From 14f4522a17db23e67a6fa17876633cc6260cb42b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 3 Feb 2014 21:37:53 -0800 Subject: [PATCH] Change many %g format specifiers to %.*g with precision DBL_DIG + 1. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The high precision should ensure that in most cases the value is formatted with enough digits to fully express the internal precision. Without this change, %g by itself only expresses 6 digits of precision, so that an integer value like 99999999 is formatted as 1e8. This fixes the problem. This commit adds a test to MISSING VALUES because this was in particular reported as a problem. Thanks to Andre Müller for reporting this issue. --- src/language/dictionary/sys-file-info.c | 13 +- src/language/lexer/value-parser.c | 11 +- src/language/stats/autorecode.c | 5 +- src/language/stats/binomial.c | 6 +- src/language/stats/cochran.c | 9 +- src/language/stats/crosstabs.q | 7 +- src/language/stats/descriptives.c | 12 +- src/language/stats/oneway.c | 6 +- src/language/stats/regression.c | 7 +- src/language/stats/runs.c | 8 +- src/language/utilities/set.q | 5 +- src/language/xforms/compute.c | 11 +- src/math/categoricals.c | 5 +- src/output/cairo-chart.c | 5 +- src/output/charts/plot-hist-cairo.c | 6 +- src/ui/gui/aggregate-dialog.c | 11 +- src/ui/gui/psppire-dialog-action-binomial.c | 6 +- src/ui/gui/psppire-dialog-action-chisquare.c | 6 +- src/ui/gui/psppire-dialog-action-factor.c | 7 +- src/ui/gui/psppire-dialog-action-logistic.c | 9 +- src/ui/gui/psppire-dialog-action-oneway.c | 8 +- src/ui/gui/psppire-val-chooser.c | 39 +++--- src/ui/gui/recode-dialog.c | 9 +- src/ui/gui/select-cases-dialog.c | 7 +- src/ui/gui/spreadsheet-test.c | 5 +- tests/data/datasheet-test.c | 12 +- tests/language/dictionary/missing-values.at | 123 ++++++++++++++++++- utilities/pspp-dump-sav.c | 31 ++--- 28 files changed, 277 insertions(+), 112 deletions(-) diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 6f73d83165..2fdbdaf3c2 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -17,6 +17,7 @@ #include #include +#include #include #include "data/attributes.h" @@ -560,11 +561,13 @@ describe_variable (const struct variable *v, struct tab_table *t, int r, double x, y; mv_get_range (mv, &x, &y); if (x == LOWEST) - cp += sprintf (cp, "LOWEST THRU %g", y); + cp += sprintf (cp, "LOWEST THRU %.*g", DBL_DIG + 1, y); else if (y == HIGHEST) - cp += sprintf (cp, "%g THRU HIGHEST", x); + cp += sprintf (cp, "%.*g THRU HIGHEST", DBL_DIG + 1, x); else - cp += sprintf (cp, "%g THRU %g", x, y); + cp += sprintf (cp, "%.*g THRU %.*g", + DBL_DIG + 1, x, + DBL_DIG + 1, y); cnt++; } for (i = 0; i < mv_n_values (mv); i++) @@ -573,7 +576,7 @@ describe_variable (const struct variable *v, struct tab_table *t, int r, if (cnt++ > 0) cp += sprintf (cp, "; "); if (var_is_numeric (v)) - cp += sprintf (cp, "%g", value->f); + cp += sprintf (cp, "%.*g", DBL_DIG + 1, value->f); else { int width = var_get_width (v); diff --git a/src/language/lexer/value-parser.c b/src/language/lexer/value-parser.c index 9d3d77f916..65e34a348b 100644 --- a/src/language/lexer/value-parser.c +++ b/src/language/lexer/value-parser.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2005, 2006, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2005, 2006, 2009, 2010, 2011, 2014 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 @@ -18,6 +18,7 @@ #include "value-parser.h" +#include #include #include "data/data-in.h" @@ -62,15 +63,15 @@ parse_num_range (struct lexer *lexer, if (*y < *x) { double t; - msg (SW, _("The high end of the range (%g) is below the low end (%g). " - "The range will be treated as if reversed."), - *y, *x); + msg (SW, _("The high end of the range (%.*g) is below the low end " + "(%.*g). The range will be treated as if reversed."), + DBL_DIG + 1, *y, DBL_DIG + 1, *x); t = *x; *x = *y; *y = t; } else if (*x == *y) - msg (SW, _("Ends of range are equal (%g)."), *x); + msg (SW, _("Ends of range are equal (%.*g)."), DBL_DIG + 1, *x); return true; } diff --git a/src/language/stats/autorecode.c b/src/language/stats/autorecode.c index 7c1b766750..dc357f7c44 100644 --- a/src/language/stats/autorecode.c +++ b/src/language/stats/autorecode.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010, 2012, 2013, 2014 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 @@ -16,6 +16,7 @@ #include +#include #include #include "data/case.h" @@ -323,7 +324,7 @@ cmd_autorecode (struct lexer *lexer, struct dataset *ds) str, src_width); } else - recoded_value = c_xasprintf ("%g", from->f); + recoded_value = c_xasprintf ("%.*g", DBL_DIG + 1, from->f); /* Remove trailing whitespace */ len = strlen (recoded_value); diff --git a/src/language/stats/binomial.c b/src/language/stats/binomial.c index 94d0d9721e..8439a71b93 100644 --- a/src/language/stats/binomial.c +++ b/src/language/stats/binomial.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2006, 2009, 2010, 2011, 2014 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 @@ -18,6 +18,7 @@ #include "language/stats/binomial.h" +#include #include #include @@ -202,7 +203,8 @@ binomial_execute (const struct dataset *ds, if ( bst->cutpoint != SYSMIS) { - ds_put_format (&catstr[0], "<= %g", bst->cutpoint); + ds_put_format (&catstr[0], "<= %.*g", + DBL_DIG + 1, bst->cutpoint); } else { diff --git a/src/language/stats/cochran.c b/src/language/stats/cochran.c index 3ea8fd342b..869e5f5c83 100644 --- a/src/language/stats/cochran.c +++ b/src/language/stats/cochran.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010, 2011, 2014 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 @@ -18,6 +18,7 @@ #include "language/stats/cochran.h" +#include #include #include @@ -169,8 +170,10 @@ show_freqs_box (const struct one_sample_test *ost, const struct cochran *ct) tab_joint_text (table, 1, 0, 2, 0, TAT_TITLE | TAB_CENTER, _("Value")); - tab_text_format (table, 1, 1, 0, _("Success (%g)"), ct->success); - tab_text_format (table, 2, 1, 0, _("Failure (%g)"), ct->failure); + tab_text_format (table, 1, 1, 0, _("Success (%.*g)"), + DBL_DIG + 1, ct->success); + tab_text_format (table, 2, 1, 0, _("Failure (%.*g)"), + DBL_DIG + 1, ct->failure); tab_hline (table, TAL_2, 0, tab_nc (table) - 1, column_headers); tab_vline (table, TAL_2, row_headers, 0, tab_nr (table) - 1); diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 6adae77b03..bcb5a0ebac 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -1944,8 +1945,8 @@ display_risk (struct pivot_table *pt, struct tab_table *risk) case 1: case 2: if (var_is_numeric (rv)) - sprintf (buf, _("For cohort %s = %g"), - var_to_string (rv), pt->rows[i - 1].f); + sprintf (buf, _("For cohort %s = %.*g"), + var_to_string (rv), DBL_DIG + 1, pt->rows[i - 1].f); else sprintf (buf, _("For cohort %s = %.*s"), var_to_string (rv), diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index 413826cc9c..f80965616f 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-2000, 2009-2013 Free Software Foundation, Inc. + Copyright (C) 1997-2000, 2009-2014 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 @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -1002,17 +1003,18 @@ display (struct dsc_proc *dsc) nc = 0; tab_text (t, nc++, i + 1, TAB_LEFT, var_to_string (dv->v)); - tab_text_format (t, nc++, i + 1, 0, "%g", dv->valid); + tab_text_format (t, nc++, i + 1, 0, "%.*g", DBL_DIG + 1, dv->valid); if (dsc->format == DSC_SERIAL) - tab_text_format (t, nc++, i + 1, 0, "%g", dv->missing); + tab_text_format (t, nc++, i + 1, 0, "%.*g", DBL_DIG + 1, dv->missing); for (j = 0; j < DSC_N_STATS; j++) if (dsc->show_stats & (1ul << j)) tab_double (t, nc++, i + 1, TAB_NONE, dv->stats[j], NULL); } - tab_title (t, _("Valid cases = %g; cases with missing value(s) = %g."), - dsc->valid, dsc->missing_listwise); + tab_title (t, _("Valid cases = %.*g; cases with missing value(s) = %.*g."), + DBL_DIG + 1, dsc->valid, + DBL_DIG + 1, dsc->missing_listwise); tab_submit (t); } diff --git a/src/language/stats/oneway.c b/src/language/stats/oneway.c index 70e6a3d0d8..807b5dc39f 100644 --- a/src/language/stats/oneway.c +++ b/src/language/stats/oneway.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -1332,7 +1333,8 @@ show_contrast_coeffs (const struct oneway_spec *cmd, const struct oneway_workspa ds_destroy (&vstr); - tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%g", coeffn->coeff); + tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%.*g", + DBL_DIG + 1, coeffn->coeff); } ++c_num; } diff --git a/src/language/stats/regression.c b/src/language/stats/regression.c index 07188663fe..0ef739a4e0 100644 --- a/src/language/stats/regression.c +++ b/src/language/stats/regression.c @@ -16,6 +16,7 @@ #include +#include #include #include @@ -949,9 +950,9 @@ reg_stats_anova (const linreg * c, const struct variable *var) /* Degrees of freedom */ - tab_text_format (t, 3, 1, TAB_RIGHT, "%g", c->dfm); - tab_text_format (t, 3, 2, TAB_RIGHT, "%g", c->dfe); - tab_text_format (t, 3, 3, TAB_RIGHT, "%g", c->dft); + tab_text_format (t, 3, 1, TAB_RIGHT, "%.*g", DBL_DIG + 1, c->dfm); + tab_text_format (t, 3, 2, TAB_RIGHT, "%.*g", DBL_DIG + 1, c->dfe); + tab_text_format (t, 3, 3, TAB_RIGHT, "%.*g", DBL_DIG + 1, c->dft); /* Mean Squares */ tab_double (t, 4, 1, TAB_RIGHT, msm, NULL); diff --git a/src/language/stats/runs.c b/src/language/stats/runs.c index b3a1b4fdd8..788aae0d13 100644 --- a/src/language/stats/runs.c +++ b/src/language/stats/runs.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. -*-c-*- - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010, 2011, 2014 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 @@ -19,6 +19,7 @@ #include "language/stats/runs.h" +#include #include #include @@ -164,8 +165,9 @@ runs_execute (const struct dataset *ds, } casegrouper_destroy (grouper); if (multimodal) - msg (MW, _("Multiple modes exist for variable `%s'. Using %g as the threshold value."), - var_get_name (var), run->cutpoint); + msg (MW, _("Multiple modes exist for variable `%s'. " + "Using %.*g as the threshold value."), + var_get_name (var), DBL_DIG + 1, run->cutpoint); } } break; diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index 9a7e841707..50ddd9443e 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -624,7 +625,7 @@ show_blanks (const struct dataset *ds UNUSED) { return (settings_get_blanks () == SYSMIS ? xstrdup ("SYSMIS") - : xasprintf ("%g", settings_get_blanks ())); + : xasprintf ("%.*g", DBL_DIG + 1, settings_get_blanks ())); } static void diff --git a/src/language/xforms/compute.c b/src/language/xforms/compute.c index 0ab4e3a4bb..00f7c5ad47 100644 --- a/src/language/xforms/compute.c +++ b/src/language/xforms/compute.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2014 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 @@ -16,6 +16,7 @@ #include +#include #include #include @@ -150,9 +151,9 @@ compute_num_vec (void *compute_, struct ccase **c, casenumber case_num) "as an index into vector %s."), vector_get_name (compute->vector)); else - msg (SW, _("When executing COMPUTE: %g is not a valid value as " + msg (SW, _("When executing COMPUTE: %.*g is not a valid value as " "an index into vector %s."), - index, vector_get_name (compute->vector)); + DBL_DIG + 1, index, vector_get_name (compute->vector)); return TRNS_CONTINUE; } @@ -208,9 +209,9 @@ compute_str_vec (void *compute_, struct ccase **c, casenumber case_num) } else if (rindx < 1 || rindx > vector_get_var_cnt (compute->vector)) { - msg (SW, _("When executing COMPUTE: %g is not a valid value as " + msg (SW, _("When executing COMPUTE: %.*g is not a valid value as " "an index into vector %s."), - index, vector_get_name (compute->vector)); + DBL_DIG + 1, index, vector_get_name (compute->vector)); return TRNS_CONTINUE; } diff --git a/src/math/categoricals.c b/src/math/categoricals.c index d89dfdbb26..b1afd11c8c 100644 --- a/src/math/categoricals.c +++ b/src/math/categoricals.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2012, 2014 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 @@ -19,6 +19,7 @@ #include "math/categoricals.h" #include "math/interaction.h" +#include #include #include "data/case.h" @@ -252,7 +253,7 @@ categoricals_dump (const struct categoricals *cat) assert (vn->var == var); - printf ("%g(%d)", val->f, valn->index); + printf ("%.*g(%d)", DBL_DIG + 1, val->f, valn->index); if (vv < iact->n_vars - 1) printf (", "); } diff --git a/src/output/cairo-chart.c b/src/output/cairo-chart.c index 42d1248146..88e70493d6 100644 --- a/src/output/cairo-chart.c +++ b/src/output/cairo-chart.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2004, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2004, 2009, 2010, 2011, 2014 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 @@ -367,7 +367,8 @@ xrchart_write_scale (cairo_t *cr, struct xrchart_geometry *geom, { double pos = (s + lower) * tick_interval; draw_tick (cr, geom, orient, false, - s * tick_interval * geom->axis[orient].scale, "%g", pos); + s * tick_interval * geom->axis[orient].scale, "%.*g", + DBL_DIG + 1, pos); } } diff --git a/src/output/charts/plot-hist-cairo.c b/src/output/charts/plot-hist-cairo.c index a9a5d44f58..93133c2e9e 100644 --- a/src/output/charts/plot-hist-cairo.c +++ b/src/output/charts/plot-hist-cairo.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2011, 2014 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 @@ -18,6 +18,7 @@ #include "output/charts/plot-hist.h" +#include #include #include "data/val-type.h" @@ -103,7 +104,8 @@ hist_draw_bar (cairo_t *cr, const struct xrchart_geometry *geom, if (label) draw_tick (cr, geom, SCALE_ABSCISSA, bins > 10, - x_pos + width / 2.0, "%g", (upper + lower) / 2.0); + x_pos + width / 2.0, "%.*g", + DBL_DIG + 1, (upper + lower) / 2.0); } void diff --git a/src/ui/gui/aggregate-dialog.c b/src/ui/gui/aggregate-dialog.c index 60a8d9f963..e89943b6c4 100644 --- a/src/ui/gui/aggregate-dialog.c +++ b/src/ui/gui/aggregate-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2010, 2011, 2012, 2013 Free Software Foundation + Copyright (C) 2010, 2011, 2012, 2013, 2014 Free Software Foundation 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 @@ -18,6 +18,7 @@ #include "dialog-common.h" +#include #include #include @@ -432,11 +433,11 @@ on_acr_change (const struct aggregate *agg, GtkTreeView *tv) gtk_entry_set_text (GTK_ENTRY (agg->summary_var_label_entry), label); gtk_entry_set_text (GTK_ENTRY (agg->summary_sv_entry), srcvar); - text = c_xasprintf ("%g", arg1); + text = c_xasprintf ("%.*g", DBL_DIG + 1, arg1); gtk_entry_set_text (GTK_ENTRY (agg->summary_arg1_entry), text); g_free (text); - text = c_xasprintf ("%g", arg2); + text = c_xasprintf ("%.*g", DBL_DIG + 1, arg2); gtk_entry_set_text (GTK_ENTRY (agg->summary_arg2_entry), text); g_free (text); @@ -681,10 +682,10 @@ append_summary_spec (const struct aggregate *agg, GtkTreeIter *iter, GString *st ds_put_cstr (&dss, srcvar); if ( arity > 0) - ds_put_c_format (&dss, ", %g", arg1); + ds_put_c_format (&dss, ", %.*g", DBL_DIG + 1, arg1); if ( arity > 1) - ds_put_c_format (&dss, ", %g", arg2); + ds_put_c_format (&dss, ", %.*g", DBL_DIG + 1, arg2); ds_put_cstr (&dss, ")"); diff --git a/src/ui/gui/psppire-dialog-action-binomial.c b/src/ui/gui/psppire-dialog-action-binomial.c index 2641684c1c..8c91ca3e05 100644 --- a/src/ui/gui/psppire-dialog-action-binomial.c +++ b/src/ui/gui/psppire-dialog-action-binomial.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2012 Free Software Foundation + Copyright (C) 2012, 2014 Free Software Foundation 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 @@ -20,6 +20,8 @@ #include "psppire-dialog-action-binomial.h" #include "psppire-value-entry.h" +#include + #include "dialog-common.h" #include "helper.h" #include @@ -141,7 +143,7 @@ generate_syntax (PsppireDialogAction *a) ds_init_cstr (&str, "NPAR TEST\n\t/BINOMIAL"); if ( get_proportion (scd, &prop)) - ds_put_c_format (&str, "(%g)", prop); + ds_put_c_format (&str, "(%.*g)", DBL_DIG + 1, prop); ds_put_cstr (&str, " ="); diff --git a/src/ui/gui/psppire-dialog-action-chisquare.c b/src/ui/gui/psppire-dialog-action-chisquare.c index 36c68c064e..5ee3e87991 100644 --- a/src/ui/gui/psppire-dialog-action-chisquare.c +++ b/src/ui/gui/psppire-dialog-action-chisquare.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2010, 2011, 2012, 2013 Free Software Foundation + Copyright (C) 2010, 2011, 2012, 2013, 2014 Free Software Foundation 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 @@ -19,6 +19,8 @@ #include "psppire-dialog-action-chisquare.h" +#include + #include "psppire-var-view.h" #include "psppire-dialog.h" @@ -80,7 +82,7 @@ generate_syntax (PsppireDialogAction *act) gtk_tree_model_get (GTK_TREE_MODEL (ls), &iter, 0, &v, -1); - ds_put_c_format (&dss, " %g", v); + ds_put_c_format (&dss, " %.*g", DBL_DIG + 1, v); } } diff --git a/src/ui/gui/psppire-dialog-action-factor.c b/src/ui/gui/psppire-dialog-action-factor.c index 2c6b3e63b3..e1edf4a483 100644 --- a/src/ui/gui/psppire-dialog-action-factor.c +++ b/src/ui/gui/psppire-dialog-action-factor.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation + Copyright (C) 2009, 2010, 2011, 2012, 2014 Free Software Foundation 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 @@ -19,6 +19,8 @@ #include "psppire-dialog-action-factor.h" +#include + #include "psppire-var-view.h" #include "dialog-common.h" #include "psppire-selector.h" @@ -71,7 +73,8 @@ generate_syntax (PsppireDialogAction *act) if ( rd->extraction.explicit_nfactors ) ds_put_c_format (&str, "FACTORS (%d)", rd->extraction.n_factors); else - ds_put_c_format (&str, "MINEIGEN (%g)", rd->extraction.mineigen); + ds_put_c_format (&str, "MINEIGEN (%.*g)", + DBL_DIG + 1, rd->extraction.mineigen); /* The CRITERIA = ITERATE subcommand is overloaded. diff --git a/src/ui/gui/psppire-dialog-action-logistic.c b/src/ui/gui/psppire-dialog-action-logistic.c index 1908bd98c7..2eec4c6b81 100644 --- a/src/ui/gui/psppire-dialog-action-logistic.c +++ b/src/ui/gui/psppire-dialog-action-logistic.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2008, 2010, 2011, 2012 Free Software Foundation + Copyright (C) 2008, 2010, 2011, 2012, 2014 Free Software Foundation 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 @@ -20,6 +20,8 @@ #include "psppire-dialog-action-logistic.h" #include "psppire-value-entry.h" +#include + #include "dialog-common.h" #include "helper.h" #include @@ -165,13 +167,14 @@ generate_syntax (PsppireDialogAction *a) ds_put_cstr (&str, "\n\t/CRITERIA ="); - syntax_gen_pspp (&str, " CUT(%g)", rd->cut_point); + syntax_gen_pspp (&str, " CUT(%.*g)", DBL_DIG + 1, rd->cut_point); syntax_gen_pspp (&str, " ITERATE(%d)", rd->max_iterations); if (rd->conf) { - syntax_gen_pspp (&str, "\n\t/PRINT = CI(%g)", rd->conf_level); + syntax_gen_pspp (&str, "\n\t/PRINT = CI(%.*g)", + DBL_DIG + 1, rd->conf_level); } if (rd->constant) diff --git a/src/ui/gui/psppire-dialog-action-oneway.c b/src/ui/gui/psppire-dialog-action-oneway.c index 66b80f6417..c817f71f15 100644 --- a/src/ui/gui/psppire-dialog-action-oneway.c +++ b/src/ui/gui/psppire-dialog-action-oneway.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2012, 2013 Free Software Foundation + Copyright (C) 2012, 2013, 2014 Free Software Foundation 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 @@ -19,6 +19,8 @@ #include "psppire-dialog-action-oneway.h" +#include + #include "psppire-var-view.h" #include "psppire-acr.h" @@ -89,7 +91,7 @@ generate_syntax (PsppireDialogAction *act) gtk_tree_model_get (GTK_TREE_MODEL (ls), &iter, 0, &v, -1); - ds_put_c_format (&dss, " %g", v); + ds_put_c_format (&dss, " %.*g", DBL_DIG + 1, v); } } @@ -177,7 +179,7 @@ list_store_changed (PsppireDialogActionOneway *csd) total += v; } - text = g_strdup_printf ("%g", total); + text = g_strdup_printf ("%.*g", DBL_DIG + 1, total); gtk_entry_set_text (GTK_ENTRY (csd->ctotal), text); diff --git a/src/ui/gui/psppire-val-chooser.c b/src/ui/gui/psppire-val-chooser.c index eb233b4ae5..c2c273542c 100644 --- a/src/ui/gui/psppire-val-chooser.c +++ b/src/ui/gui/psppire-val-chooser.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2011 Free Software Foundation + Copyright (C) 2011, 2014 Free Software Foundation 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 @@ -16,6 +16,7 @@ #include +#include #include #include "dialog-common.h" #include "psppire-val-chooser.h" @@ -452,7 +453,7 @@ old_value_to_string (const GValue *src, GValue *dest) { case OV_NUMERIC: { - gchar *text = g_strdup_printf ("%g", ov->v.v); + gchar *text = g_strdup_printf ("%.*g", DBL_DIG + 1, ov->v.v); g_value_set_string (dest, text); g_free (text); } @@ -476,10 +477,10 @@ old_value_to_string (const GValue *src, GValue *dest) g_unichar_to_utf8 (0x2013, en_dash); - text = g_strdup_printf ("%g %s %g", - ov->v.range[0], - en_dash, - ov->v.range[1]); + text = g_strdup_printf ("%.*g %s %.*g", + DBL_DIG + 1, ov->v.range[0], + en_dash, + DBL_DIG + 1, ov->v.range[1]); g_value_set_string (dest, text); g_free (text); } @@ -491,9 +492,9 @@ old_value_to_string (const GValue *src, GValue *dest) g_unichar_to_utf8 (0x2013, en_dash); - text = g_strdup_printf ("LOWEST %s %g", + text = g_strdup_printf ("LOWEST %s %.*g", en_dash, - ov->v.range[1]); + DBL_DIG + 1, ov->v.range[1]); g_value_set_string (dest, text); g_free (text); @@ -506,8 +507,8 @@ old_value_to_string (const GValue *src, GValue *dest) g_unichar_to_utf8 (0x2013, en_dash); - text = g_strdup_printf ("%g %s HIGHEST", - ov->v.range[0], + text = g_strdup_printf ("%.*g %s HIGHEST", + DBL_DIG + 1, ov->v.range[0], en_dash); g_value_set_string (dest, text); @@ -548,7 +549,7 @@ old_value_append_syntax (struct string *str, const struct old_value *ov) switch (ov->type) { case OV_NUMERIC: - ds_put_c_format (str, "%g", ov->v.v); + ds_put_c_format (str, "%.*g", DBL_DIG + 1, ov->v.v); break; case OV_STRING: { @@ -568,17 +569,17 @@ old_value_append_syntax (struct string *str, const struct old_value *ov) ds_put_cstr (str, "ELSE"); break; case OV_RANGE: - ds_put_c_format (str, "%g THRU %g", - ov->v.range[0], - ov->v.range[1]); + ds_put_c_format (str, "%.*g THRU %.*g", + DBL_DIG + 1, ov->v.range[0], + DBL_DIG + 1, ov->v.range[1]); break; case OV_LOW_UP: - ds_put_c_format (str, "LOWEST THRU %g", - ov->v.range[1]); + ds_put_c_format (str, "LOWEST THRU %*gg", + DBL_DIG + 1, ov->v.range[1]); break; case OV_HIGH_DOWN: - ds_put_c_format (str, "%g THRU HIGHEST", - ov->v.range[0]); + ds_put_c_format (str, "%.*g THRU HIGHEST", + DBL_DIG + 1, ov->v.range[0]); break; default: g_warning ("Invalid type in old recode value"); @@ -612,7 +613,7 @@ psppire_val_chooser_get_status (PsppireValChooser *vr, struct old_value *ov) static gchar * num_to_string (gdouble x) { - return g_strdup_printf ("%g", x); + return g_strdup_printf ("%.*g", DBL_DIG + 1, x); } diff --git a/src/ui/gui/recode-dialog.c b/src/ui/gui/recode-dialog.c index f8d21336e1..4ef8ae216d 100644 --- a/src/ui/gui/recode-dialog.c +++ b/src/ui/gui/recode-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2009, 2010, 2011, 2012 Free Software Foundation + Copyright (C) 2007, 2009, 2010, 2011, 2012, 2014 Free Software Foundation 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 @@ -30,6 +30,7 @@ #include +#include #include #include #include @@ -104,7 +105,7 @@ new_value_to_string (const GValue *src, GValue *dest) { case NV_NUMERIC: { - gchar *text = g_strdup_printf ("%g", nv->v.v); + gchar *text = g_strdup_printf ("%.*g", DBL_DIG + 1, nv->v.v); g_value_set_string (dest, text); g_free (text); } @@ -314,7 +315,7 @@ recode_different_dialog (PsppireDataWindow *de) static gchar * num_to_string (gdouble x) { - return g_strdup_printf ("%g", x); + return g_strdup_printf ("%.*g", DBL_DIG + 1, x); } /* Callback which gets called when a new row is selected @@ -956,7 +957,7 @@ new_value_append_syntax (struct string *dds, const struct new_value *nv) switch (nv->type) { case NV_NUMERIC: - ds_put_c_format (dds, "%g", nv->v.v); + ds_put_c_format (dds, "%.*g", DBL_DIG + 1, nv->v.v); break; case NV_STRING: syntax_gen_string (dds, ss_cstr (nv->v.s)); diff --git a/src/ui/gui/select-cases-dialog.c b/src/ui/gui/select-cases-dialog.c index c3bc123c05..2b4634808b 100644 --- a/src/ui/gui/select-cases-dialog.c +++ b/src/ui/gui/select-cases-dialog.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2014 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 @@ -17,6 +17,7 @@ #include #include "select-cases-dialog.h" +#include #include #include "executor.h" #include "psppire-dialog.h" @@ -388,9 +389,9 @@ generate_syntax_filter (const struct select_cases_dialog *scd) gtk_spin_button_get_value (GTK_SPIN_BUTTON (scd->spinbutton)); ds_put_c_format (&dss, - "COMPUTE %s = RV.UNIFORM (0,1) < %g.\n", + "COMPUTE %s = RV.UNIFORM (0,1) < %.*g.\n", filter, - percentage / 100.0 ); + DBL_DIG + 1, percentage / 100.0 ); } else { diff --git a/src/ui/gui/spreadsheet-test.c b/src/ui/gui/spreadsheet-test.c index bec577821a..af0d18c81c 100644 --- a/src/ui/gui/spreadsheet-test.c +++ b/src/ui/gui/spreadsheet-test.c @@ -1,5 +1,5 @@ /* PSPPIRE - a graphical user interface for PSPP. - Copyright (C) 2013 Free Software Foundation + Copyright (C) 2013, 2014 Free Software Foundation 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 @@ -19,6 +19,7 @@ #include +#include #include #include "psppire-spreadsheet-model.h" @@ -78,7 +79,7 @@ on_clicked (GtkButton *button, struct xxx *stuff) const int width = caseproto_get_width (proto, i); const union value *val = case_data_idx (c, i); if (0 == width) - printf ("%g ", val->f); + printf ("%.*g ", DBL_DIG + 1, val->f); else { char *ss = xzalloc (width + 1); diff --git a/tests/data/datasheet-test.c b/tests/data/datasheet-test.c index 532b883faa..db21ff33fe 100644 --- a/tests/data/datasheet-test.c +++ b/tests/data/datasheet-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2014 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 @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -153,9 +154,10 @@ check_datasheet_casereader (struct mc *mc, struct casereader *reader, { if (width == 0) mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " - "%g != %g", + "%.*g != %.*g", row, col, n_rows, n_columns, - case_num_idx (c, col), array[row][col].f); + DBL_DIG + 1, case_num_idx (c, col), + DBL_DIG + 1, array[row][col].f); else mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " "'%.*s' != '%.*s'", @@ -217,8 +219,8 @@ check_datasheet (struct mc *mc, struct datasheet *ds, { if (width == 0) mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " - "%g != %g", row, col, n_rows, n_columns, - v.f, av->f); + "%.*g != %.*g", row, col, n_rows, n_columns, + DBL_DIG + 1, v.f, DBL_DIG + 1, av->f); else mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " "'%.*s' != '%.*s'", diff --git a/tests/language/dictionary/missing-values.at b/tests/language/dictionary/missing-values.at index 75254462aa..84ee172529 100644 --- a/tests/language/dictionary/missing-values.at +++ b/tests/language/dictionary/missing-values.at @@ -7,38 +7,159 @@ DATA LIST NOTABLE/str1 1-5 (A) str2 6-8 (A) date1 9-19 (DATE) num1 20-25 * Numeric missing values. MISSING VALUES date1 num1 (1). +DISPLAY DICTIONARY date1 num1. MISSING VALUES date1 num1 (1, 2). +DISPLAY DICTIONARY date1 num1. MISSING VALUES date1 num1 (1, 2, 3). +DISPLAY DICTIONARY date1 num1. +MISSING VALUES date1 num1 (9999998, 9999984, 3). +DISPLAY DICTIONARY date1 num1. * Numeric missing values using the first variable's format. MISSING VALUES num1 date1 ('1'). +DISPLAY DICTIONARY date1 num1. MISSING VALUES num1 date1 ('1', '2'). +DISPLAY DICTIONARY date1 num1. MISSING VALUES num1 date1 ('1', '2', '3'). +DISPLAY DICTIONARY date1 num1. MISSING VALUES date1 num1 ('06-AUG-05'). +DISPLAY DICTIONARY date1 num1. MISSING VALUES date1 num1 ('06-AUG-05', '01-OCT-78'). +DISPLAY DICTIONARY date1 num1. MISSING VALUES date1 num1 ('06-AUG-05', '01-OCT-78', '14-FEB-81'). +DISPLAY DICTIONARY date1 num1. * Ranges of numeric missing values. MISSING VALUES num1 (1 THRU 2). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (LO THRU 2). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (LOWEST THRU 2). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (1 THRU HI). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (1 THRU HIGHEST). +DISPLAY DICTIONARY num1. * A range of numeric missing values, plus an individual value. MISSING VALUES num1 (1 THRU 2, 3). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (LO THRU 2, 3). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (LOWEST THRU 2, 3). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (1 THRU HI, -1). +DISPLAY DICTIONARY num1. MISSING VALUES num1 (1 THRU HIGHEST, -1). +DISPLAY DICTIONARY num1. * String missing values. MISSING VALUES str1 str2 longstr ('abc ','def'). +DISPLAY DICTIONARY str1 str2 longstr. * May mix variable types when clearing missing values. MISSING VALUES ALL (). +DISPLAY DICTIONARY +]) +AT_CHECK([pspp -o pspp.csv missing-values.sps]) +AT_CHECK([sed -n '/Format/s/,.*/:/p +s/"//g +s/^,Missing Values: \([[^,]]*\),.*/\1/p +/^$/p' pspp.csv +], [0], [dnl +date1: +1 +num1: +1 + +date1: +1; 2 +num1: +1; 2 + +date1: +1; 2; 3 +num1: +1; 2; 3 + +date1: +9999998; 9999984; 3 +num1: +9999998; 9999984; 3 + +date1: +1 +num1: +1 + +date1: +1; 2 +num1: +1; 2 + +date1: +1; 2; 3 +num1: +1; 2; 3 + +date1: +13342665600 +num1: +13342665600 + +date1: +13342665600; 12495427200 +num1: +13342665600; 12495427200 + +date1: +13342665600; 12495427200; 12570336000 +num1: +13342665600; 12495427200; 12570336000 + +num1: +1 THRU 2 + +num1: +LOWEST THRU 2 + +num1: +LOWEST THRU 2 + +num1: +1 THRU HIGHEST + +num1: +1 THRU HIGHEST + +num1: +1 THRU 2; 3 + +num1: +LOWEST THRU 2; 3 + +num1: +LOWEST THRU 2; 3 + +num1: +1 THRU HIGHEST; -1 + +num1: +1 THRU HIGHEST; -1 + +str1: +abc ; def @&t@ +str2: +abc; def +longstr: +abc ; def @&t@ + +str1: +str2: +date1: +num1: +longstr: ]) -AT_CHECK([pspp -O format=csv missing-values.sps]) AT_CLEANUP AT_SETUP([MISSING VALUES invalid cases]) diff --git a/utilities/pspp-dump-sav.c b/utilities/pspp-dump-sav.c index ceabd1d57d..788c34f76b 100644 --- a/utilities/pspp-dump-sav.c +++ b/utilities/pspp-dump-sav.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 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 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -332,7 +333,7 @@ read_header (struct sfm_reader *r) : ""); printf ("\t%17s: %"PRId32"\n", "Weight index", weight_index); printf ("\t%17s: %"PRId32"\n", "Number of cases", ncases); - printf ("\t%17s: %g\n", "Compression bias", r->bias); + printf ("\t%17s: %.*g\n", "Compression bias", DBL_DIG + 1, r->bias); printf ("\t%17s: %s\n", "Creation date", creation_date); printf ("\t%17s: %s\n", "Creation time", creation_time); printf ("\t%17s: \"%s\"\n", "File label", file_label); @@ -476,11 +477,11 @@ read_variable_record (struct sfm_reader *r) { double low = read_float (r); double high = read_float (r); - printf (" %g...%g", low, high); + printf (" %.*g...%.*g", DBL_DIG + 1, low, DBL_DIG + 1, high); missing_value_code = -missing_value_code - 2; } for (i = 0; i < missing_value_code; i++) - printf (" %g", read_float (r)); + printf (" %.*g", DBL_DIG + 1, read_float (r)); } else if (width > 0) { @@ -509,7 +510,7 @@ print_untyped_value (struct sfm_reader *r, char raw_value[8]) if (!isprint (raw_value[n_printable])) break; - printf ("%g/\"%.*s\"", value, n_printable, raw_value); + printf ("%.*g/\"%.*s\"", DBL_DIG + 1, value, n_printable, raw_value); } /* Reads value labels from sysfile R and inserts them into the @@ -718,20 +719,20 @@ read_machine_float_info (struct sfm_reader *r, size_t size, size_t count) sys_error (r, "Bad size (%zu) or count (%zu) on extension 4.", size, count); - printf ("\tsysmis: %g (%a)\n", sysmis, sysmis); + printf ("\tsysmis: %.*g (%a)\n", DBL_DIG + 1, sysmis, sysmis); if (sysmis != SYSMIS) - sys_warn (r, "File specifies unexpected value %g (%a) as %s.", - sysmis, sysmis, "SYSMIS"); + sys_warn (r, "File specifies unexpected value %.*g (%a) as %s.", + DBL_DIG + 1, sysmis, sysmis, "SYSMIS"); - printf ("\thighest: %g (%a)\n", highest, highest); + printf ("\thighest: %.*g (%a)\n", DBL_DIG + 1, highest, highest); if (highest != HIGHEST) - sys_warn (r, "File specifies unexpected value %g (%a) as %s.", - highest, highest, "HIGHEST"); + sys_warn (r, "File specifies unexpected value %.*g (%a) as %s.", + DBL_DIG + 1, highest, highest, "HIGHEST"); - printf ("\tlowest: %g (%a)\n", lowest, lowest); + printf ("\tlowest: %.*g (%a)\n", DBL_DIG + 1, lowest, lowest); if (lowest != LOWEST && lowest != SYSMIS) - sys_warn (r, "File specifies unexpected value %g (%a) as %s.", - lowest, lowest, "LOWEST"); + sys_warn (r, "File specifies unexpected value %.*g (%a) as %s.", + DBL_DIG + 1, lowest, lowest, "LOWEST"); } static void @@ -1254,7 +1255,7 @@ read_simple_compressed_data (struct sfm_reader *r, int max_cases) switch (opcode) { default: - printf ("%g", opcode - r->bias); + printf ("%.*g", DBL_DIG + 1, opcode - r->bias); if (width != 0) printf (", but this is a string variable (width=%d)", width); printf ("\n"); -- 2.30.2