From: Martin Möhrmann Date: Wed, 15 Feb 2017 11:41:02 +0000 (+0100) Subject: fmt: support sharp flag for float and complex value printing X-Git-Tag: go1.9beta1~1504 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e97f407ec164174187d6fbb2f7332d6fb3176e9e;p=gostls13.git fmt: support sharp flag for float and complex value printing 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 --- diff --git a/src/fmt/doc.go b/src/fmt/doc.go index a2faecb36e..f0ac448d64 100644 --- a/src/fmt/doc.go +++ b/src/fmt/doc.go @@ -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 @@ -109,6 +109,8 @@ 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) diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go index b7089be1a1..9bec6f3f9e 100644 --- a/src/fmt/fmt_test.go +++ b/src/fmt/fmt_test.go @@ -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)"}, diff --git a/src/fmt/format.go b/src/fmt/format.go index f77048338a..d4b92f8121 100644 --- a/src/fmt/format.go +++ b/src/fmt/format.go @@ -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.