1
0
mirror of https://github.com/golang/go synced 2024-11-18 07:04:52 -07:00

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>
This commit is contained in:
Robert Griesemer 2015-05-27 14:43:30 -07:00
parent 5ee552815c
commit 0c02b33acd
3 changed files with 17 additions and 9 deletions

View File

@ -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 @@ 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
}
}

View 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"},

View 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