From b8fcae02b076cdef0bbef5bce5de090409858fba Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 3 Feb 2015 15:13:26 -0800 Subject: [PATCH] math/big: fix %b format so it matches strconf %b format for non-zero values (For zero values the strconv %b format prints the bias-adjusted exponent; there's no bias in Float.) Change-Id: I6f4dda9c3a50d02eac375cfe2c927c1540aae865 Reviewed-on: https://go-review.googlesource.com/3841 Reviewed-by: Alan Donovan --- src/math/big/floatconv.go | 12 ++-- src/math/big/floatconv_test.go | 106 +++++++++++++++++---------------- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/src/math/big/floatconv.go b/src/math/big/floatconv.go index a1b234f144..06c1f14471 100644 --- a/src/math/big/floatconv.go +++ b/src/math/big/floatconv.go @@ -205,12 +205,6 @@ func (x *Float) String() string { return x.Format('p', 0) } -// TODO(gri) The 'b' and 'p' formats have different meanings here than -// in strconv: in strconv, the printed exponent is the biased (hardware) -// exponent; here it is the unbiased exponent. Decide what to do. -// (a strconv 'p' formatted float value can only be interpreted correctly -// if the bias is known; i.e., we must know if it's a 32bit or 64bit number). - // bstring appends the string of x in the format ["-"] mantissa "p" exponent // with a decimal mantissa and a binary exponent, or ["-"] "0" if x is zero, // and returns the extended buffer. @@ -233,7 +227,11 @@ func (x *Float) bstring(buf []byte) []byte { } buf = append(buf, m.decimalString()...) buf = append(buf, 'p') - return strconv.AppendInt(buf, int64(x.exp), 10) + e := int64(x.exp) - int64(x.prec) + if e >= 0 { + buf = append(buf, '+') + } + return strconv.AppendInt(buf, e, 10) } // pstring appends the string of x in the format ["-"] "0x." mantissa "p" exponent diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go index 83ea1d6057..0e8bfb39ab 100644 --- a/src/math/big/floatconv_test.go +++ b/src/math/big/floatconv_test.go @@ -9,55 +9,53 @@ import ( "testing" ) -var floatSetFloat64StringTests = []struct { - s string - x float64 -}{ - {"0", 0}, - {"-0", -0}, - {"+0", 0}, - {"1", 1}, - {"-1", -1}, - {"+1", 1}, - {"1.234", 1.234}, - {"-1.234", -1.234}, - {"+1.234", 1.234}, - {".1", 0.1}, - {"1.", 1}, - {"+1.", 1}, - - {"0e100", 0}, - {"-0e+100", 0}, - {"+0e-100", 0}, - {"0E100", 0}, - {"-0E+100", 0}, - {"+0E-100", 0}, - {"0p100", 0}, - {"-0p+100", 0}, - {"+0p-100", 0}, +func TestFloatSetFloat64String(t *testing.T) { + for _, test := range []struct { + s string + x float64 + }{ + {"0", 0}, + {"-0", -0}, + {"+0", 0}, + {"1", 1}, + {"-1", -1}, + {"+1", 1}, + {"1.234", 1.234}, + {"-1.234", -1.234}, + {"+1.234", 1.234}, + {".1", 0.1}, + {"1.", 1}, + {"+1.", 1}, - {"1.e10", 1e10}, - {"1e+10", 1e10}, - {"+1e-10", 1e-10}, - {"1E10", 1e10}, - {"1.E+10", 1e10}, - {"+1E-10", 1e-10}, - {"1p10", 1 << 10}, - {"1p+10", 1 << 10}, - {"+1.p-10", 1.0 / (1 << 10)}, + {"0e100", 0}, + {"-0e+100", 0}, + {"+0e-100", 0}, + {"0E100", 0}, + {"-0E+100", 0}, + {"+0E-100", 0}, + {"0p100", 0}, + {"-0p+100", 0}, + {"+0p-100", 0}, - {"-687436.79457e-245", -687436.79457e-245}, - {"-687436.79457E245", -687436.79457e245}, - {"1024.p-12", 0.25}, - {"-1.p10", -1024}, - {"0.25p2", 1}, + {"1.e10", 1e10}, + {"1e+10", 1e10}, + {"+1e-10", 1e-10}, + {"1E10", 1e10}, + {"1.E+10", 1e10}, + {"+1E-10", 1e-10}, + {"1p10", 1 << 10}, + {"1p+10", 1 << 10}, + {"+1.p-10", 1.0 / (1 << 10)}, - {".0000000000000000000000000000000000000001", 1e-40}, - {"+10000000000000000000000000000000000000000e-0", 1e40}, -} + {"-687436.79457e-245", -687436.79457e-245}, + {"-687436.79457E245", -687436.79457e245}, + {"1024.p-12", 0.25}, + {"-1.p10", -1024}, + {"0.25p2", 1}, -func TestFloatSetFloat64String(t *testing.T) { - for _, test := range floatSetFloat64StringTests { + {".0000000000000000000000000000000000000001", 1e-40}, + {"+10000000000000000000000000000000000000000e-0", 1e40}, + } { var x Float x.prec = 53 // TODO(gri) find better solution _, ok := x.SetString(test.s) @@ -82,8 +80,9 @@ func TestFloatFormat(t *testing.T) { }{ {"0", 'b', 0, "0"}, {"-0", 'b', 0, "-0"}, - {"1.0", 'b', 0, "4503599627370496p1"}, - {"-1.0", 'b', 0, "-4503599627370496p1"}, + {"1.0", 'b', 0, "4503599627370496p-52"}, + {"-1.0", 'b', 0, "-4503599627370496p-52"}, + {"4503599627370496", 'b', 0, "4503599627370496p+0"}, {"0", 'p', 0, "0"}, {"-0", 'p', 0, "-0"}, @@ -95,14 +94,21 @@ func TestFloatFormat(t *testing.T) { t.Error(err) continue } + f := new(Float).SetFloat64(f64) got := f.Format(test.format, test.prec) if got != test.want { - t.Errorf("%v: got %s", test, got) + t.Errorf("%v: got %s; want %s", test, got, test.want) } - if test.format == 'b' || test.format == 'p' { - continue // 'b', 'p' format not supported or different in strconv.Format + + if test.format == 'b' && f64 == 0 { + continue // 'b' format in strconv.Float requires knowledge of bias for 0.0 } + if test.format == 'p' { + continue // 'p' format not supported in strconv.Format + } + + // verify that Float format matches strconv format want := strconv.FormatFloat(f64, test.format, test.prec, 64) if got != want { t.Errorf("%v: got %s; want %s", test, got, want) -- 2.48.1