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:
parent
5ee552815c
commit
0c02b33acd
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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"},
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user