summaryrefslogtreecommitdiffstats
path: root/generic/tclUtil.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2011-03-01 04:16:27 (GMT)
committerKevin B Kenny <kennykb@acm.org>2011-03-01 04:16:27 (GMT)
commitb153d7d08398bacf50287f086acee27748d21799 (patch)
treefe0d74fb715de8a7a2d9ae7bfd47e54e1114fc38 /generic/tclUtil.c
parent7c4049a13f83930bf6a57ef889abc9e49fa414ec (diff)
parentcd34f84f42b4e64866a9177553e91417ded252a0 (diff)
downloadtcl-b153d7d08398bacf50287f086acee27748d21799.zip
tcl-b153d7d08398bacf50287f086acee27748d21799.tar.gz
tcl-b153d7d08398bacf50287f086acee27748d21799.tar.bz2
merge trunk
Diffstat (limited to 'generic/tclUtil.c')
-rw-r--r--generic/tclUtil.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c
index 2e435e6..3a42a32 100644
--- a/generic/tclUtil.c
+++ b/generic/tclUtil.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUtil.c,v 1.117.2.3 2010/12/11 18:39:29 kennykb Exp $
+ * RCS: @(#) $Id: tclUtil.c,v 1.124 2011/01/15 18:10:19 kennykb Exp $
*/
#include "tclInt.h"
@@ -2268,12 +2268,52 @@ Tcl_PrintDouble(
/*
* Ordinary (normal and denormal) values.
*/
-
+
if (*precisionPtr == 0) {
digits = TclDoubleDigits(value, -1, TCL_DD_SHORTEST,
&exponent, &signum, &end);
} else {
- digits = TclDoubleDigits(value, *precisionPtr, TCL_DD_E_FORMAT,
+ /*
+ * There are at least two possible interpretations for tcl_precision.
+ *
+ * The first is, "choose the decimal representation having
+ * $tcl_precision digits of significance that is nearest to the
+ * given number, breaking ties by rounding to even, and then
+ * trimming trailing zeros." This gives the greatest possible
+ * precision in the decimal string, but offers the anomaly that
+ * [expr 0.1] will be "0.10000000000000001".
+ *
+ * The second is "choose the decimal representation having at
+ * most $tcl_precision digits of significance that is nearest
+ * to the given number. If no such representation converts
+ * exactly to the given number, choose the one that is closest,
+ * breaking ties by rounding to even. If more than one such
+ * representation converts exactly to the given number, choose
+ * the shortest, breaking ties in favour of the nearest, breaking
+ * remaining ties in favour of the one ending in an even digit."
+ *
+ * Tcl 8.4 implements the first of these, which gives rise to
+ * anomalies in formatting:
+ *
+ * % expr 0.1
+ * 0.10000000000000001
+ * % expr 0.01
+ * 0.01
+ * % expr 1e-7
+ * 9.9999999999999995e-08
+ *
+ * For human readability, it appears better to choose the second rule,
+ * and let [expr 0.1] return 0.1. But for 8.4 compatibility, we
+ * prefer the first (the recommended zero value for tcl_precision
+ * avoids the problem entirely).
+ *
+ * Uncomment TCL_DD_SHORTEN_FLAG in the next call to prefer the
+ * method that allows floating point values to be shortened if
+ * it can be done without loss of precision.
+ */
+
+ digits = TclDoubleDigits(value, *precisionPtr,
+ TCL_DD_E_FORMAT /* | TCL_DD_SHORTEN_FLAG */,
&exponent, &signum, &end);
}
if (signum) {
@@ -2294,7 +2334,15 @@ Tcl_PrintDouble(
c = *++p;
}
}
- sprintf(dst, "e%+d", exponent);
+ /*
+ * Tcl 8.4 appears to format with at least a two-digit exponent;
+ * preserve that behaviour when tcl_precision != 0
+ */
+ if (*precisionPtr == 0) {
+ sprintf(dst, "e%+d", exponent);
+ } else {
+ sprintf(dst, "e%+03d", exponent);
+ }
} else {
/*
* F format for others.