math/big: fix latent decimal conversion bug
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>
diff --git a/src/math/big/decimal.go b/src/math/big/decimal.go
index 3d024dc..2595e5f 100644
--- a/src/math/big/decimal.go
+++ b/src/math/big/decimal.go
@@ -19,12 +19,14 @@
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 @@
// special case 0
if len(m) == 0 {
x.mant = x.mant[:0]
+ x.exp = 0
return
}
@@ -255,4 +258,7 @@
i--
}
x.mant = x.mant[:i]
+ if i == 0 {
+ x.exp = 0
+ }
}
diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go
index db30031..9fc2b89 100644
--- a/src/math/big/floatconv_test.go
+++ b/src/math/big/floatconv_test.go
@@ -125,12 +125,16 @@
{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"},
diff --git a/src/math/big/ftoa.go b/src/math/big/ftoa.go
index 0f943e1..4c3e743 100644
--- a/src/math/big/ftoa.go
+++ b/src/math/big/ftoa.go
@@ -58,7 +58,7 @@
}
// Inf
- if x.IsInf() {
+ if x.form == inf {
if !x.neg {
buf = append(buf, '+')
}
@@ -79,12 +79,10 @@
// 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