]> Cypherpunks.ru repositories - gostls13.git/commitdiff
fmt: format hex floats and complexes
authorRuss Cox <rsc@golang.org>
Wed, 30 Jan 2019 03:13:54 +0000 (22:13 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 26 Feb 2019 05:16:49 +0000 (05:16 +0000)
This CL modifies fmt's printer to implement %x and %X
for formatting floating-point data (floats and complexes)
in standard hexadecimal notation.

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

For #29008.
Vet update is #29986.

Change-Id: If2842a11631bc393a1ebcf6914ed07658652af5a
Reviewed-on: https://go-review.googlesource.com/c/160245
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
src/fmt/doc.go
src/fmt/fmt_test.go
src/fmt/format.go
src/fmt/print.go

index 3b657f3681dbabdc6eb60646e5834ec7e9f621b2..c349f8e321ffee94858839b7b8235d03e4e4b4e0 100644 (file)
@@ -40,6 +40,8 @@
                %F      synonym for %f
                %g      %e for large exponents, %f otherwise. Precision is discussed below.
                %G      %E for large exponents, %F otherwise
+               %x      hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20
+               %X      upper-case hexadecimal notation, e.g. -0X1.23ABCP+20
        String and slice of bytes (treated equivalently with these verbs):
                %s      the uninterpreted bytes of the string or slice
                %q      a double-quoted string safely escaped with Go syntax
index 068c2620a8a20955f053fad109261ab4e197533a..2d10c7a8418923e9b7c9edb048745a8d591637d5 100644 (file)
@@ -413,6 +413,8 @@ var fmtTests = []struct {
        // floats
        {"%+.3e", 0.0, "+0.000e+00"},
        {"%+.3e", 1.0, "+1.000e+00"},
+       {"%+.3x", 0.0, "+0x0.000p+00"},
+       {"%+.3x", 1.0, "+0x1.000p+00"},
        {"%+.3f", -1.0, "-1.000"},
        {"%+.3F", -1.0, "-1.000"},
        {"%+.3F", float32(-1.0), "-1.000"},
@@ -428,6 +430,8 @@ var fmtTests = []struct {
        {"%+10.2f", -1.0, "     -1.00"},
        {"% .3E", -1.0, "-1.000E+00"},
        {"% .3e", 1.0, " 1.000e+00"},
+       {"% .3X", -1.0, "-0X1.000P+00"},
+       {"% .3x", 1.0, " 0x1.000p+00"},
        {"%+.3g", 0.0, "+0"},
        {"%+.3g", 1.0, "+1"},
        {"%+.3g", -1.0, "-1"},
@@ -445,17 +449,21 @@ var fmtTests = []struct {
        {"%#g", 1000000.0, "1.00000e+06"},
        {"%#.0f", 1.0, "1."},
        {"%#.0e", 1.0, "1.e+00"},
+       {"%#.0x", 1.0, "0x1.p+00"},
        {"%#.0g", 1.0, "1."},
        {"%#.0g", 1100000.0, "1.e+06"},
        {"%#.4f", 1.0, "1.0000"},
        {"%#.4e", 1.0, "1.0000e+00"},
+       {"%#.4x", 1.0, "0x1.0000p+00"},
        {"%#.4g", 1.0, "1.000"},
        {"%#.4g", 100000.0, "1.000e+05"},
        {"%#.0f", 123.0, "123."},
        {"%#.0e", 123.0, "1.e+02"},
+       {"%#.0x", 123.0, "0x1.p+07"},
        {"%#.0g", 123.0, "1.e+02"},
        {"%#.4f", 123.0, "123.0000"},
        {"%#.4e", 123.0, "1.2300e+02"},
+       {"%#.4x", 123.0, "0x1.ec00p+06"},
        {"%#.4g", 123.0, "123.0"},
        {"%#.4g", 123000.0, "1.230e+05"},
        {"%#9.4g", 1.0, "    1.000"},
@@ -474,17 +482,23 @@ var fmtTests = []struct {
        {"%20f", posInf, "                +Inf"},
        {"% 20F", posInf, "                 Inf"},
        {"% 20e", negInf, "                -Inf"},
+       {"% 20x", negInf, "                -Inf"},
        {"%+20E", negInf, "                -Inf"},
+       {"%+20X", negInf, "                -Inf"},
        {"% +20g", negInf, "                -Inf"},
        {"%+-20G", posInf, "+Inf                "},
        {"%20e", NaN, "                 NaN"},
+       {"%20x", NaN, "                 NaN"},
        {"% +20E", NaN, "                +NaN"},
+       {"% +20X", NaN, "                +NaN"},
        {"% -20g", NaN, " NaN                "},
        {"%+-20G", NaN, "+NaN                "},
        // Zero padding does not apply to infinities and NaN.
        {"%+020e", posInf, "                +Inf"},
+       {"%+020x", posInf, "                +Inf"},
        {"%-020f", negInf, "-Inf                "},
        {"%-020E", NaN, "NaN                 "},
+       {"%-020X", NaN, "NaN                 "},
 
        // complex values
        {"%.f", 0i, "(0+0i)"},
@@ -492,23 +506,29 @@ var fmtTests = []struct {
        {"%+.f", 0i, "(+0+0i)"},
        {"% +.f", 0i, "(+0+0i)"},
        {"%+.3e", 0i, "(+0.000e+00+0.000e+00i)"},
+       {"%+.3x", 0i, "(+0x0.000p+00+0x0.000p+00i)"},
        {"%+.3f", 0i, "(+0.000+0.000i)"},
        {"%+.3g", 0i, "(+0+0i)"},
        {"%+.3e", 1 + 2i, "(+1.000e+00+2.000e+00i)"},
+       {"%+.3x", 1 + 2i, "(+0x1.000p+00+0x1.000p+01i)"},
        {"%+.3f", 1 + 2i, "(+1.000+2.000i)"},
        {"%+.3g", 1 + 2i, "(+1+2i)"},
        {"%.3e", 0i, "(0.000e+00+0.000e+00i)"},
+       {"%.3x", 0i, "(0x0.000p+00+0x0.000p+00i)"},
        {"%.3f", 0i, "(0.000+0.000i)"},
        {"%.3F", 0i, "(0.000+0.000i)"},
        {"%.3F", complex64(0i), "(0.000+0.000i)"},
        {"%.3g", 0i, "(0+0i)"},
        {"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"},
+       {"%.3x", 1 + 2i, "(0x1.000p+00+0x1.000p+01i)"},
        {"%.3f", 1 + 2i, "(1.000+2.000i)"},
        {"%.3g", 1 + 2i, "(1+2i)"},
        {"%.3e", -1 - 2i, "(-1.000e+00-2.000e+00i)"},
+       {"%.3x", -1 - 2i, "(-0x1.000p+00-0x1.000p+01i)"},
        {"%.3f", -1 - 2i, "(-1.000-2.000i)"},
        {"%.3g", -1 - 2i, "(-1-2i)"},
        {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
+       {"% .3X", -1 - 2i, "(-0X1.000P+00-0X1.000P+01i)"},
        {"%+.3g", 1 + 2i, "(+1+2i)"},
        {"%+.3g", complex64(1 + 2i), "(+1+2i)"},
        {"%#g", 1 + 2i, "(1.00000+2.00000i)"},
@@ -517,11 +537,13 @@ var fmtTests = []struct {
        {"%#g", -1e10 - 1.11e100i, "(-1.00000e+10-1.11000e+100i)"},
        {"%#.0f", 1.23 + 1.0i, "(1.+1.i)"},
        {"%#.0e", 1.23 + 1.0i, "(1.e+00+1.e+00i)"},
+       {"%#.0x", 1.23 + 1.0i, "(0x1.p+00+0x1.p+00i)"},
        {"%#.0g", 1.23 + 1.0i, "(1.+1.i)"},
        {"%#.0g", 0 + 100000i, "(0.+1.e+05i)"},
        {"%#.0g", 1230000 + 0i, "(1.e+06+0.i)"},
        {"%#.4f", 1 + 1.23i, "(1.0000+1.2300i)"},
        {"%#.4e", 123 + 1i, "(1.2300e+02+1.0000e+00i)"},
+       {"%#.4x", 123 + 1i, "(0x1.ec00p+06+0x1.0000p+00i)"},
        {"%#.4g", 123 + 1.23i, "(123.0+1.230i)"},
        {"%#12.5g", 0 + 100000i, "(      0.0000 +1.0000e+05i)"},
        {"%#12.5g", 1230000 - 0i, "(  1.2300e+06     +0.0000i)"},
@@ -541,7 +563,9 @@ var fmtTests = []struct {
        {"% f", complex(negInf, negInf), "(-Inf-Infi)"},
        {"% f", complex(NaN, NaN), "( NaN+NaNi)"},
        {"%8e", complex(posInf, posInf), "(    +Inf    +Infi)"},
+       {"%8x", complex(posInf, posInf), "(    +Inf    +Infi)"},
        {"% 8E", complex(posInf, posInf), "(     Inf    +Infi)"},
+       {"% 8X", complex(posInf, posInf), "(     Inf    +Infi)"},
        {"%+8f", complex(negInf, negInf), "(    -Inf    -Infi)"},
        {"% +8g", complex(negInf, negInf), "(    -Inf    -Infi)"},
        {"% -8G", complex(NaN, NaN), "( NaN    +NaN    i)"},
index d6da8aed1e3aad72b5c76f381c00333a0cb4f2a6..6d939080957c92e87a484bfb8539b3cc94b3e5ce 100644 (file)
@@ -510,7 +510,7 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
        if f.sharp && verb != 'b' {
                digits := 0
                switch verb {
-               case 'v', 'g', 'G':
+               case 'v', 'g', 'G', 'x':
                        digits = prec
                        // If no precision is set explicitly use a precision of 6.
                        if digits == -1 {
@@ -519,8 +519,8 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
                }
 
                // Buffer pre-allocated with enough room for
-               // exponent notations of the form "e+123".
-               var tailBuf [5]byte
+               // exponent notations of the form "e+123" or "p-1023".
+               var tailBuf [6]byte
                tail := tailBuf[:0]
 
                hasDecimalPoint := false
@@ -529,9 +529,16 @@ func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) {
                        switch num[i] {
                        case '.':
                                hasDecimalPoint = true
-                       case 'e', 'E':
+                       case 'p', 'P':
                                tail = append(tail, num[i:]...)
                                num = num[:i]
+                       case 'e', 'E':
+                               if verb != 'x' && verb != 'X' {
+                                       tail = append(tail, num[i:]...)
+                                       num = num[:i]
+                                       break
+                               }
+                               fallthrough
                        default:
                                digits--
                        }
index 42fcd8b979b01e5f1cce657085621c7546636da7..9976b8d2636fc05093d36001246cf267eb457ecb 100644 (file)
@@ -407,7 +407,7 @@ func (p *pp) fmtFloat(v float64, size int, verb rune) {
        switch verb {
        case 'v':
                p.fmt.fmtFloat(v, size, 'g', -1)
-       case 'b', 'g', 'G':
+       case 'b', 'g', 'G', 'x', 'X':
                p.fmt.fmtFloat(v, size, verb, -1)
        case 'f', 'e', 'E':
                p.fmt.fmtFloat(v, size, verb, 6)
@@ -425,7 +425,7 @@ func (p *pp) fmtComplex(v complex128, size int, verb rune) {
        // Make sure any unsupported verbs are found before the
        // calls to fmtFloat to not generate an incorrect error string.
        switch verb {
-       case 'v', 'b', 'g', 'G', 'f', 'F', 'e', 'E':
+       case 'v', 'b', 'g', 'G', 'x', 'X', 'f', 'F', 'e', 'E':
                oldPlus := p.fmt.plus
                p.buf.WriteByte('(')
                p.fmtFloat(real(v), size/2, verb)