Commit 675503c5 authored by Russ Cox's avatar Russ Cox

math/big: add %x float format

big.Float already had %p for printing hex format,
but that format normalizes differently from fmt's %x
and ignores precision entirely.

This CL adds %x to big.Float, matching fmt's behavior:
the verb is spelled 'x' not 'p', the mantissa is normalized
to [1, 2), and precision is respected.

See golang.org/design/19308-number-literals for background.

For #29008.

Change-Id: I9c1b9612107094856797e5b0b584c556c1914895
Reviewed-on: https://go-review.googlesource.com/c/160249Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 1e58bb14
...@@ -268,7 +268,7 @@ func TestFloat64Text(t *testing.T) { ...@@ -268,7 +268,7 @@ func TestFloat64Text(t *testing.T) {
{32, 'g', -1, "32"}, {32, 'g', -1, "32"},
{32, 'g', 0, "3e+01"}, {32, 'g', 0, "3e+01"},
// {100, 'x', -1, "%x"}, {100, 'x', -1, "0x1.9p+06"},
// {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs // {math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs // {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
...@@ -339,115 +339,166 @@ func actualPrec(x float64) uint { ...@@ -339,115 +339,166 @@ func actualPrec(x float64) uint {
} }
func TestFloatText(t *testing.T) { func TestFloatText(t *testing.T) {
const defaultRound = ^RoundingMode(0)
for _, test := range []struct { for _, test := range []struct {
x string x string
round RoundingMode
prec uint prec uint
format byte format byte
digits int digits int
want string want string
}{ }{
{"0", 10, 'f', 0, "0"}, {"0", defaultRound, 10, 'f', 0, "0"},
{"-0", 10, 'f', 0, "-0"}, {"-0", defaultRound, 10, 'f', 0, "-0"},
{"1", 10, 'f', 0, "1"}, {"1", defaultRound, 10, 'f', 0, "1"},
{"-1", 10, 'f', 0, "-1"}, {"-1", defaultRound, 10, 'f', 0, "-1"},
{"1.459", 100, 'e', 0, "1e+00"}, {"1.459", defaultRound, 100, 'e', 0, "1e+00"},
{"2.459", 100, 'e', 1, "2.5e+00"}, {"2.459", defaultRound, 100, 'e', 1, "2.5e+00"},
{"3.459", 100, 'e', 2, "3.46e+00"}, {"3.459", defaultRound, 100, 'e', 2, "3.46e+00"},
{"4.459", 100, 'e', 3, "4.459e+00"}, {"4.459", defaultRound, 100, 'e', 3, "4.459e+00"},
{"5.459", 100, 'e', 4, "5.4590e+00"}, {"5.459", defaultRound, 100, 'e', 4, "5.4590e+00"},
{"1.459", 100, 'E', 0, "1E+00"}, {"1.459", defaultRound, 100, 'E', 0, "1E+00"},
{"2.459", 100, 'E', 1, "2.5E+00"}, {"2.459", defaultRound, 100, 'E', 1, "2.5E+00"},
{"3.459", 100, 'E', 2, "3.46E+00"}, {"3.459", defaultRound, 100, 'E', 2, "3.46E+00"},
{"4.459", 100, 'E', 3, "4.459E+00"}, {"4.459", defaultRound, 100, 'E', 3, "4.459E+00"},
{"5.459", 100, 'E', 4, "5.4590E+00"}, {"5.459", defaultRound, 100, 'E', 4, "5.4590E+00"},
{"1.459", 100, 'f', 0, "1"}, {"1.459", defaultRound, 100, 'f', 0, "1"},
{"2.459", 100, 'f', 1, "2.5"}, {"2.459", defaultRound, 100, 'f', 1, "2.5"},
{"3.459", 100, 'f', 2, "3.46"}, {"3.459", defaultRound, 100, 'f', 2, "3.46"},
{"4.459", 100, 'f', 3, "4.459"}, {"4.459", defaultRound, 100, 'f', 3, "4.459"},
{"5.459", 100, 'f', 4, "5.4590"}, {"5.459", defaultRound, 100, 'f', 4, "5.4590"},
{"1.459", 100, 'g', 0, "1"}, {"1.459", defaultRound, 100, 'g', 0, "1"},
{"2.459", 100, 'g', 1, "2"}, {"2.459", defaultRound, 100, 'g', 1, "2"},
{"3.459", 100, 'g', 2, "3.5"}, {"3.459", defaultRound, 100, 'g', 2, "3.5"},
{"4.459", 100, 'g', 3, "4.46"}, {"4.459", defaultRound, 100, 'g', 3, "4.46"},
{"5.459", 100, 'g', 4, "5.459"}, {"5.459", defaultRound, 100, 'g', 4, "5.459"},
{"1459", 53, 'g', 0, "1e+03"}, {"1459", defaultRound, 53, 'g', 0, "1e+03"},
{"2459", 53, 'g', 1, "2e+03"}, {"2459", defaultRound, 53, 'g', 1, "2e+03"},
{"3459", 53, 'g', 2, "3.5e+03"}, {"3459", defaultRound, 53, 'g', 2, "3.5e+03"},
{"4459", 53, 'g', 3, "4.46e+03"}, {"4459", defaultRound, 53, 'g', 3, "4.46e+03"},
{"5459", 53, 'g', 4, "5459"}, {"5459", defaultRound, 53, 'g', 4, "5459"},
{"1459", 53, 'G', 0, "1E+03"}, {"1459", defaultRound, 53, 'G', 0, "1E+03"},
{"2459", 53, 'G', 1, "2E+03"}, {"2459", defaultRound, 53, 'G', 1, "2E+03"},
{"3459", 53, 'G', 2, "3.5E+03"}, {"3459", defaultRound, 53, 'G', 2, "3.5E+03"},
{"4459", 53, 'G', 3, "4.46E+03"}, {"4459", defaultRound, 53, 'G', 3, "4.46E+03"},
{"5459", 53, 'G', 4, "5459"}, {"5459", defaultRound, 53, 'G', 4, "5459"},
{"3", 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"}, {"3", defaultRound, 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
{"3", 10, 'f', 40, "3.0000000000000000000000000000000000000000"}, {"3", defaultRound, 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
{"3", 10, 'g', 40, "3"}, {"3", defaultRound, 10, 'g', 40, "3"},
{"3e40", 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"}, {"3e40", defaultRound, 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
{"3e40", 100, 'f', 4, "30000000000000000000000000000000000000000.0000"}, {"3e40", defaultRound, 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
{"3e40", 100, 'g', 40, "3e+40"}, {"3e40", defaultRound, 100, 'g', 40, "3e+40"},
// make sure "stupid" exponents don't stall the machine // make sure "stupid" exponents don't stall the machine
{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"}, {"1e1000000", defaultRound, 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
{"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"}, {"1e646456992", defaultRound, 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
{"1e646456993", 64, 'p', 0, "+Inf"}, {"1e646456993", defaultRound, 64, 'p', 0, "+Inf"},
{"1e1000000000", 64, 'p', 0, "+Inf"}, {"1e1000000000", defaultRound, 64, 'p', 0, "+Inf"},
{"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"}, {"1e-1000000", defaultRound, 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
{"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"}, {"1e-646456993", defaultRound, 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
{"1e-646456994", 64, 'p', 0, "0"}, {"1e-646456994", defaultRound, 64, 'p', 0, "0"},
{"1e-1000000000", 64, 'p', 0, "0"}, {"1e-1000000000", defaultRound, 64, 'p', 0, "0"},
// minimum and maximum values // minimum and maximum values
{"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"}, {"1p2147483646", defaultRound, 64, 'p', 0, "0x.8p+2147483647"},
{"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"}, {"0x.8p2147483647", defaultRound, 64, 'p', 0, "0x.8p+2147483647"},
{"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"}, {"0x.8p-2147483647", defaultRound, 64, 'p', 0, "0x.8p-2147483647"},
{"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"}, {"1p-2147483649", defaultRound, 64, 'p', 0, "0x.8p-2147483648"},
// TODO(gri) need tests for actual large Floats // TODO(gri) need tests for actual large Floats
{"0", 53, 'b', 0, "0"}, {"0", defaultRound, 53, 'b', 0, "0"},
{"-0", 53, 'b', 0, "-0"}, {"-0", defaultRound, 53, 'b', 0, "-0"},
{"1.0", 53, 'b', 0, "4503599627370496p-52"}, {"1.0", defaultRound, 53, 'b', 0, "4503599627370496p-52"},
{"-1.0", 53, 'b', 0, "-4503599627370496p-52"}, {"-1.0", defaultRound, 53, 'b', 0, "-4503599627370496p-52"},
{"4503599627370496", 53, 'b', 0, "4503599627370496p+0"}, {"4503599627370496", defaultRound, 53, 'b', 0, "4503599627370496p+0"},
// issue 9939 // issue 9939
{"3", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"3", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"03", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"03", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"3.", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.0", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"3.0", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.00", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"3.00", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3.000", 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"}, {"3.000", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
{"3", 350, 'p', 0, "0x.cp+2"}, {"3", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"03", 350, 'p', 0, "0x.cp+2"}, {"03", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"3.", 350, 'p', 0, "0x.cp+2"}, {"3.", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"3.0", 350, 'p', 0, "0x.cp+2"}, {"3.0", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"3.00", 350, 'p', 0, "0x.cp+2"}, {"3.00", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"3.000", 350, 'p', 0, "0x.cp+2"}, {"3.000", defaultRound, 350, 'p', 0, "0x.cp+2"},
{"0", 64, 'p', 0, "0"}, {"0", defaultRound, 64, 'p', 0, "0"},
{"-0", 64, 'p', 0, "-0"}, {"-0", defaultRound, 64, 'p', 0, "-0"},
{"1024.0", 64, 'p', 0, "0x.8p+11"}, {"1024.0", defaultRound, 64, 'p', 0, "0x.8p+11"},
{"-1024.0", 64, 'p', 0, "-0x.8p+11"}, {"-1024.0", defaultRound, 64, 'p', 0, "-0x.8p+11"},
// unsupported format {"0", defaultRound, 64, 'x', -1, "0x0p+00"},
//{"3.14", 64, 'x', 0, "%x"}, {"0", defaultRound, 64, 'x', 0, "0x0p+00"},
//{"-3.14", 64, 'x', 0, "%x"}, {"0", defaultRound, 64, 'x', 1, "0x0.0p+00"},
{"0", defaultRound, 64, 'x', 5, "0x0.00000p+00"},
{"3.25", defaultRound, 64, 'x', 0, "0x1p+02"},
{"-3.25", defaultRound, 64, 'x', 0, "-0x1p+02"},
{"3.25", defaultRound, 64, 'x', 1, "0x1.ap+01"},
{"-3.25", defaultRound, 64, 'x', 1, "-0x1.ap+01"},
{"3.25", defaultRound, 64, 'x', -1, "0x1.ap+01"},
{"-3.25", defaultRound, 64, 'x', -1, "-0x1.ap+01"},
{"1024.0", defaultRound, 64, 'x', 0, "0x1p+10"},
{"-1024.0", defaultRound, 64, 'x', 0, "-0x1p+10"},
{"1024.0", defaultRound, 64, 'x', 5, "0x1.00000p+10"},
{"8191.0", defaultRound, 53, 'x', -1, "0x1.fffp+12"},
{"8191.5", defaultRound, 53, 'x', -1, "0x1.fff8p+12"},
{"8191.53125", defaultRound, 53, 'x', -1, "0x1.fff88p+12"},
{"8191.53125", defaultRound, 53, 'x', 4, "0x1.fff8p+12"},
{"8191.53125", defaultRound, 53, 'x', 3, "0x1.000p+13"},
{"8191.53125", defaultRound, 53, 'x', 0, "0x1p+13"},
{"8191.533203125", defaultRound, 53, 'x', -1, "0x1.fff888p+12"},
{"8191.533203125", defaultRound, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.533203125", defaultRound, 53, 'x', 4, "0x1.fff9p+12"},
{"8191.53125", defaultRound, 53, 'x', -1, "0x1.fff88p+12"},
{"8191.53125", ToNearestEven, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", ToNearestAway, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", ToZero, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", AwayFromZero, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", ToNegativeInf, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", ToPositiveInf, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.53125", defaultRound, 53, 'x', 4, "0x1.fff8p+12"},
{"8191.53125", defaultRound, 53, 'x', 3, "0x1.000p+13"},
{"8191.53125", defaultRound, 53, 'x', 0, "0x1p+13"},
{"8191.533203125", defaultRound, 53, 'x', -1, "0x1.fff888p+12"},
{"8191.533203125", defaultRound, 53, 'x', 6, "0x1.fff888p+12"},
{"8191.533203125", defaultRound, 53, 'x', 5, "0x1.fff88p+12"},
{"8191.533203125", defaultRound, 53, 'x', 4, "0x1.fff9p+12"},
{"8191.53125", ToNearestEven, 53, 'x', 4, "0x1.fff8p+12"},
{"8191.53125", ToNearestAway, 53, 'x', 4, "0x1.fff9p+12"},
{"8191.53125", ToZero, 53, 'x', 4, "0x1.fff8p+12"},
{"8191.53125", ToZero, 53, 'x', 2, "0x1.ffp+12"},
{"8191.53125", AwayFromZero, 53, 'x', 4, "0x1.fff9p+12"},
{"8191.53125", ToNegativeInf, 53, 'x', 4, "0x1.fff8p+12"},
{"-8191.53125", ToNegativeInf, 53, 'x', 4, "-0x1.fff9p+12"},
{"8191.53125", ToPositiveInf, 53, 'x', 4, "0x1.fff9p+12"},
{"-8191.53125", ToPositiveInf, 53, 'x', 4, "-0x1.fff8p+12"},
} { } {
f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven) f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
if err != nil { if err != nil {
t.Errorf("%v: %s", test, err) t.Errorf("%v: %s", test, err)
continue continue
} }
if test.round != defaultRound {
f.SetMode(test.round)
}
got := f.Text(test.format, test.digits) got := f.Text(test.format, test.digits)
if got != test.want { if got != test.want {
...@@ -458,7 +509,7 @@ func TestFloatText(t *testing.T) { ...@@ -458,7 +509,7 @@ func TestFloatText(t *testing.T) {
// ('p' format is not supported by strconv.FormatFloat, // ('p' format is not supported by strconv.FormatFloat,
// and its output for 0.0 prints a biased exponent value // and its output for 0.0 prints a biased exponent value
// as in 0p-1074 which makes no sense to emulate here) // as in 0p-1074 which makes no sense to emulate here)
if test.prec == 53 && test.format != 'p' && f.Sign() != 0 { if test.prec == 53 && test.format != 'p' && f.Sign() != 0 && (test.round == ToNearestEven || test.round == defaultRound) {
f64, acc := f.Float64() f64, acc := f.Float64()
if acc != Exact { if acc != Exact {
t.Errorf("%v: expected exact conversion to float64", test) t.Errorf("%v: expected exact conversion to float64", test)
......
...@@ -22,24 +22,28 @@ import ( ...@@ -22,24 +22,28 @@ import (
// 'f' -ddddd.dddd, no exponent // 'f' -ddddd.dddd, no exponent
// 'g' like 'e' for large exponents, like 'f' otherwise // 'g' like 'e' for large exponents, like 'f' otherwise
// 'G' like 'E' for large exponents, like 'f' otherwise // 'G' like 'E' for large exponents, like 'f' otherwise
// 'b' -ddddddp±dd, binary exponent // 'x' -0xd.dddddp±dd, hexadecimal mantissa, decimal power of two exponent
// 'p' -0x.dddp±dd, binary exponent, hexadecimal mantissa // 'p' -0x.dddp±dd, hexadecimal mantissa, decimal power of two exponent (non-standard)
// 'b' -ddddddp±dd, decimal mantissa, decimal power of two exponent (non-standard)
// //
// For the binary exponent formats, the mantissa is printed in normalized form: // For the power-of-two exponent formats, the mantissa is printed in normalized form:
// //
// 'b' decimal integer mantissa using x.Prec() bits, or -0 // 'x' hexadecimal mantissa in [1, 2), or 0
// 'p' hexadecimal fraction with 0.5 <= 0.mantissa < 1.0, or -0 // 'p' hexadecimal mantissa in [½, 1), or 0
// 'b' decimal integer mantissa using x.Prec() bits, or 0
//
// Note that the 'x' form is the one used by most other languages and libraries.
// //
// If format is a different character, Text returns a "%" followed by the // If format is a different character, Text returns a "%" followed by the
// unrecognized format character. // unrecognized format character.
// //
// The precision prec controls the number of digits (excluding the exponent) // The precision prec controls the number of digits (excluding the exponent)
// printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f' // printed by the 'e', 'E', 'f', 'g', 'G', and 'x' formats.
// it is the number of digits after the decimal point. For 'g' and 'G' it is // For 'e', 'E', 'f', and 'x', it is the number of digits after the decimal point.
// the total number of digits. A negative precision selects the smallest // For 'g' and 'G' it is the total number of digits. A negative precision selects
// number of decimal digits necessary to identify the value x uniquely using // the smallest number of decimal digits necessary to identify the value x uniquely
// x.Prec() mantissa bits. // using x.Prec() mantissa bits.
// The prec value is ignored for the 'b' or 'p' format. // The prec value is ignored for the 'b' and 'p' formats.
func (x *Float) Text(format byte, prec int) string { func (x *Float) Text(format byte, prec int) string {
cap := 10 // TODO(gri) determine a good/better value here cap := 10 // TODO(gri) determine a good/better value here
if prec > 0 { if prec > 0 {
...@@ -76,6 +80,8 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte { ...@@ -76,6 +80,8 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
return x.fmtB(buf) return x.fmtB(buf)
case 'p': case 'p':
return x.fmtP(buf) return x.fmtP(buf)
case 'x':
return x.fmtX(buf, prec)
} }
// Algorithm: // Algorithm:
...@@ -308,6 +314,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte { ...@@ -308,6 +314,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte {
// The mantissa is normalized such that is uses x.Prec() bits in binary // The mantissa is normalized such that is uses x.Prec() bits in binary
// representation. // representation.
// The sign of x is ignored, and x must not be an Inf. // The sign of x is ignored, and x must not be an Inf.
// (The caller handles Inf before invoking fmtB.)
func (x *Float) fmtB(buf []byte) []byte { func (x *Float) fmtB(buf []byte) []byte {
if x.form == zero { if x.form == zero {
return append(buf, '0') return append(buf, '0')
...@@ -336,11 +343,80 @@ func (x *Float) fmtB(buf []byte) []byte { ...@@ -336,11 +343,80 @@ func (x *Float) fmtB(buf []byte) []byte {
return strconv.AppendInt(buf, e, 10) return strconv.AppendInt(buf, e, 10)
} }
// fmtX appends the string of x in the format "0x1." mantissa "p" exponent
// with a hexadecimal mantissa and a binary exponent, or "0x0p0" if x is zero,
// and returns the extended buffer.
// A non-zero mantissa is normalized such that 1.0 <= mantissa < 2.0.
// The sign of x is ignored, and x must not be an Inf.
// (The caller handles Inf before invoking fmtX.)
func (x *Float) fmtX(buf []byte, prec int) []byte {
if x.form == zero {
buf = append(buf, "0x0"...)
if prec > 0 {
buf = append(buf, '.')
for i := 0; i < prec; i++ {
buf = append(buf, '0')
}
}
buf = append(buf, "p+00"...)
return buf
}
if debugFloat && x.form != finite {
panic("non-finite float")
}
// round mantissa to n bits
var n uint
if prec < 0 {
n = 1 + (x.MinPrec()-1+3)/4*4 // round MinPrec up to 1 mod 4
} else {
n = 1 + 4*uint(prec)
}
// n%4 == 1
x = new(Float).SetPrec(n).SetMode(x.mode).Set(x)
// adjust mantissa to use exactly n bits
m := x.mant
switch w := uint(len(x.mant)) * _W; {
case w < n:
m = nat(nil).shl(m, n-w)
case w > n:
m = nat(nil).shr(m, w-n)
}
exp := x.exp - 1
hm := m.utoa(16)
if debugFloat && hm[0] != '1' {
panic("incorrect mantissa: " + string(hm))
}
buf = append(buf, "0x1"...)
if len(hm) > 1 {
buf = append(buf, '.')
buf = append(buf, hm[1:]...)
}
buf = append(buf, 'p')
exp64 := int64(exp)
if exp64 >= 0 {
buf = append(buf, '+')
} else {
exp64 = -exp64
buf = append(buf, '-')
}
// Force at least two exponent digits, to match fmt.
if exp64 < 10 {
buf = append(buf, '0')
}
return strconv.AppendInt(buf, exp64, 10)
}
// fmtP appends the string of x in the format "0x." mantissa "p" exponent // fmtP appends the string of x in the format "0x." mantissa "p" exponent
// with a hexadecimal mantissa and a binary exponent, or "0" if x is zero, // with a hexadecimal mantissa and a binary exponent, or "0" if x is zero,
// and returns the extended buffer. // and returns the extended buffer.
// The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0. // The mantissa is normalized such that 0.5 <= 0.mantissa < 1.0.
// The sign of x is ignored, and x must not be an Inf. // The sign of x is ignored, and x must not be an Inf.
// (The caller handles Inf before invoking fmtP.)
func (x *Float) fmtP(buf []byte) []byte { func (x *Float) fmtP(buf []byte) []byte {
if x.form == zero { if x.form == zero {
return append(buf, '0') return append(buf, '0')
...@@ -380,7 +456,7 @@ var _ fmt.Formatter = &floatZero // *Float must implement fmt.Formatter ...@@ -380,7 +456,7 @@ var _ fmt.Formatter = &floatZero // *Float must implement fmt.Formatter
// Format implements fmt.Formatter. It accepts all the regular // Format implements fmt.Formatter. It accepts all the regular
// formats for floating-point numbers ('b', 'e', 'E', 'f', 'F', // formats for floating-point numbers ('b', 'e', 'E', 'f', 'F',
// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the // 'g', 'G', 'x') as well as 'p' and 'v'. See (*Float).Text for the
// interpretation of 'p'. The 'v' format is handled like 'g'. // interpretation of 'p'. The 'v' format is handled like 'g'.
// Format also supports specification of the minimum precision // Format also supports specification of the minimum precision
// in digits, the output field width, as well as the format flags // in digits, the output field width, as well as the format flags
...@@ -394,7 +470,7 @@ func (x *Float) Format(s fmt.State, format rune) { ...@@ -394,7 +470,7 @@ func (x *Float) Format(s fmt.State, format rune) {
} }
switch format { switch format {
case 'e', 'E', 'f', 'b', 'p': case 'e', 'E', 'f', 'b', 'p', 'x':
// nothing to do // nothing to do
case 'F': case 'F':
// (*Float).Text doesn't support 'F'; handle like 'f' // (*Float).Text doesn't support 'F'; handle like 'f'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment