]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: support sharp flag for float and complex value printing
authorMartin Möhrmann <moehrmann@google.com>
Wed, 15 Feb 2017 11:41:02 +0000 (12:41 +0100)
committerMartin Möhrmann <moehrmann@google.com>
Sun, 19 Feb 2017 07:18:56 +0000 (07:18 +0000)
Added an alternate form of printing floats and complex values
by specifying the sharp flag.

Output formatted using the the verbs v, e, E, f, F, g and G in
combination with the sharp flag will always include a decimal point.

The alternate form specified by the sharp flag for %g and %G verbs
will not truncate trailing zeros and assume a default precision of 6.

Fixes #18857.

Change-Id: I4d776239e06d7a6a90f2d8556240a359888cb7c3
Reviewed-on: https://go-review.googlesource.com/37051
Reviewed-by: Rob Pike <r@golang.org>
src/fmt/doc.go
src/fmt/fmt_test.go
src/fmt/format.go

index a2faecb36e1e3f67a04629bfc8af4210d1d4acae..f0ac448d642114c7c3a382e0b1e2d3726698d2c0 100644 (file)
@@ -94,7 +94,7 @@
        precision sets the number of places after the decimal, if appropriate,
        except that for %g/%G precision sets the total number of significant
        digits. For example, given 12.345 the format %6.3f prints 12.345 while
-       %.3g prints 12.3. The default precision for %e and %f is 6; for %g it
+       %.3g prints 12.3. The default precision for %e, %f and %#g is 6; for %g it
        is the smallest number of digits necessary to identify the value uniquely.
 
        For complex numbers, the width and precision apply to the two
                        0X for hex (%#X); suppress 0x for %p (%#p);
                        for %q, print a raw (backquoted) string if strconv.CanBackquote
                        returns true;
+                       always print a decimal point for %e, %E, %f, %F, %g and %G;
+                       do not remove trailing zeros for %g and %G;
                        write e.g. U+0078 'x' if the character is printable for %U (%#U).
                ' '     (space) leave a space for elided sign in numbers (% d);
                        put spaces between bytes printing strings or slices in hex (% x, % X)
index b7089be1a1b1adc9ce97f69be39650a7c5439953..9bec6f3f9efe062eb26c36d2d9aa4bd5910bc615 100644 (file)
@@ -416,6 +416,32 @@ var fmtTests = []struct {
        {"% .3g", 1.0, " 1"},
        {"%b", float32(1.0), "8388608p-23"},
        {"%b", 1.0, "4503599627370496p-52"},
+       // Test sharp flag used with floats.
+       {"%#g", 1e-323, "1.00000e-323"},
+       {"%#g", -1.0, "-1.00000"},
+       {"%#g", 1.1, "1.10000"},
+       {"%#g", 123456.0, "123456."},
+       {"%#g", 1234567.0, "1.234567e+06"},
+       {"%#g", 1230000.0, "1.23000e+06"},
+       {"%#g", 1000000.0, "1.00000e+06"},
+       {"%#.0f", 1.0, "1."},
+       {"%#.0e", 1.0, "1.e+00"},
+       {"%#.0g", 1.0, "1."},
+       {"%#.0g", 1100000.0, "1.e+06"},
+       {"%#.4f", 1.0, "1.0000"},
+       {"%#.4e", 1.0, "1.0000e+00"},
+       {"%#.4g", 1.0, "1.000"},
+       {"%#.4g", 100000.0, "1.000e+05"},
+       {"%#.0f", 123.0, "123."},
+       {"%#.0e", 123.0, "1.e+02"},
+       {"%#.0g", 123.0, "1.e+02"},
+       {"%#.4f", 123.0, "123.0000"},
+       {"%#.4e", 123.0, "1.2300e+02"},
+       {"%#.4g", 123.0, "123.0"},
+       {"%#.4g", 123000.0, "1.230e+05"},
+       {"%#9.4g", 1.0, "    1.000"},
+       // The sharp flag has no effect for binary float format.
+       {"%#b", 1.0, "4503599627370496p-52"},
        // Precision has no effect for binary float format.
        {"%.4b", float32(1.0), "8388608p-23"},
        {"%.4b", -1.0, "-4503599627370496p-52"},
@@ -466,8 +492,24 @@ var fmtTests = []struct {
        {"% .3E", -1 - 2i, "(-1.000E+00-2.000E+00i)"},
        {"%+.3g", 1 + 2i, "(+1+2i)"},
        {"%+.3g", complex64(1 + 2i), "(+1+2i)"},
+       {"%#g", 1 + 2i, "(1.00000+2.00000i)"},
+       {"%#g", 123456 + 789012i, "(123456.+789012.i)"},
+       {"%#g", 1e-10i, "(0.00000+1.00000e-10i)"},
+       {"%#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)"},
+       {"%#.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)"},
+       {"%#.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)"},
        {"%b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
        {"%b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
+       // The sharp flag has no effect for binary complex format.
+       {"%#b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
        // Precision has no effect for binary complex format.
        {"%.4b", 1 + 2i, "(4503599627370496p-52+4503599627370496p-51i)"},
        {"%.4b", complex64(1 + 2i), "(8388608p-23+8388608p-22i)"},
index f77048338aed034d436e9fe46eb476333d6558dc..d4b92f812148f392bd4ace92a3cb3ae8a7b0f976 100644 (file)
@@ -480,6 +480,46 @@ func (f *fmt) fmt_float(v float64, size int, verb rune, prec int) {
                f.zero = oldZero
                return
        }
+       // The sharp flag forces printing a decimal point for non-binary formats
+       // and retains trailing zeros, which we may need to restore.
+       if f.sharp && verb != 'b' {
+               digits := 0
+               switch verb {
+               case 'v', 'g', 'G':
+                       digits = prec
+                       // If no precision is set explicitly use a precision of 6.
+                       if digits == -1 {
+                               digits = 6
+                       }
+               }
+
+               // Buffer pre-allocated with enough room for
+               // exponent notations of the form "e+123".
+               var tailBuf [5]byte
+               tail := tailBuf[:0]
+
+               hasDecimalPoint := false
+               // Starting from i = 1 to skip sign at num[0].
+               for i := 1; i < len(num); i++ {
+                       switch num[i] {
+                       case '.':
+                               hasDecimalPoint = true
+                       case 'e', 'E':
+                               tail = append(tail, num[i:]...)
+                               num = num[:i]
+                       default:
+                               digits--
+                       }
+               }
+               if !hasDecimalPoint {
+                       num = append(num, '.')
+               }
+               for digits > 0 {
+                       num = append(num, '0')
+                       digits--
+               }
+               num = append(num, tail...)
+       }
        // We want a sign if asked for and if the sign is not positive.
        if f.plus || num[0] != '+' {
                // If we're zero padding to the left we want the sign before the leading zeros.