]> Cypherpunks repositories - gostls13.git/commitdiff
math/big: fix latent decimal conversion bug
authorRobert Griesemer <gri@golang.org>
Wed, 27 May 2015 21:43:30 +0000 (14:43 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 28 May 2015 16:02:32 +0000 (16:02 +0000)
A decimal represented 0.0 with a 0-length mantissa and undefined
exponent, but the formatting code assumes a valid zero exponent
if the float value is 0.0. The code worked because we allocate a
new decimal value each time and because there's no rounding that
lead to 0.0.

Change-Id: Ifd771d7709de83b87fdbf141786286b4c3e13d4f
Reviewed-on: https://go-review.googlesource.com/10448
Reviewed-by: Alan Donovan <adonovan@google.com>
src/math/big/decimal.go
src/math/big/floatconv_test.go
src/math/big/ftoa.go

index 3d024dce68c345ba5a296680a12d4c315201b6b7..2595e5f8c121fb096a25977a21f1dbd646f525b3 100644 (file)
 
 package big
 
-// A decimal represents a floating-point number in decimal representation.
-// The value of a decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
-// with the most-significant mantissa digit at index 0.
+// A decimal represents an unsigned floating-point number in decimal representation.
+// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// with the most-significant mantissa digit at index 0. For the zero decimal, the
+// mantissa length and exponent are 0.
+// The zero value for decimal represents a ready-to-use 0.0.
 type decimal struct {
        mant []byte // mantissa ASCII digits, big-endian
-       exp  int    // exponent, valid if len(mant) > 0
+       exp  int    // exponent
 }
 
 // Maximum shift amount that can be done in one pass without overflow.
@@ -46,6 +48,7 @@ func (x *decimal) init(m nat, shift int) {
        // special case 0
        if len(m) == 0 {
                x.mant = x.mant[:0]
+               x.exp = 0
                return
        }
 
@@ -255,4 +258,7 @@ func trim(x *decimal) {
                i--
        }
        x.mant = x.mant[:i]
+       if i == 0 {
+               x.exp = 0
+       }
 }
index db300314f1d9f831c28a46da8d2f156497bb6a48..9fc2b89fb92413aa49c2ebcaab0e4b134c4ab5da 100644 (file)
@@ -125,12 +125,16 @@ func TestFloat64Format(t *testing.T) {
                {1, 'f', 0, "1"},
                {-1, 'f', 0, "-1"},
 
+               {0.001, 'e', 0, "1e-03"},
+               {0.459, 'e', 0, "5e-01"},
                {1.459, 'e', 0, "1e+00"},
                {2.459, 'e', 1, "2.5e+00"},
                {3.459, 'e', 2, "3.46e+00"},
                {4.459, 'e', 3, "4.459e+00"},
                {5.459, 'e', 4, "5.4590e+00"},
 
+               {0.001, 'f', 0, "0"},
+               {0.459, 'f', 0, "0"},
                {1.459, 'f', 0, "1"},
                {2.459, 'f', 1, "2.5"},
                {3.459, 'f', 2, "3.46"},
index 0f943e1ff27ea1f67fd5a8bb8db259f8abd6e737..4c3e743d6cb6ea9ac28b2a631fbbf85a092eaf25 100644 (file)
@@ -58,7 +58,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
        }
 
        // Inf
-       if x.IsInf() {
+       if x.form == inf {
                if !x.neg {
                        buf = append(buf, '+')
                }
@@ -79,12 +79,10 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
        //   3) read digits out and format
 
        // 1) convert Float to multiprecision decimal
-       var mant nat
+       var d decimal // == 0.0
        if x.form == finite {
-               mant = x.mant
+               d.init(x.mant, int(x.exp)-x.mant.bitLen())
        }
-       var d decimal
-       d.init(mant, int(x.exp)-x.mant.bitLen())
 
        // 2) round to desired precision
        shortest := false