strconv: simplify code for binary exponent float format

Use optimized formatBits function to format mantissa and exponent.
Add benchmark for binary exponent float format.

on darwin/386

benchmark                         old ns/op     new ns/op     delta
BenchmarkAppendFloatBinaryExp     520           122           -76.54%

on darwin/amd64

benchmark                         old ns/op     new ns/op     delta
BenchmarkAppendFloatBinaryExp     76.9          84.3          +9.62%

Change-Id: If543552f1960e1655bed3a4130914e5eaa3aac69
Reviewed-on: https://go-review.googlesource.com/5600
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go
index f885d96..d59c78e 100644
--- a/src/strconv/ftoa.go
+++ b/src/strconv/ftoa.go
@@ -47,7 +47,7 @@
 
 // AppendFloat appends the string form of the floating-point number f,
 // as generated by FormatFloat, to dst and returns the extended buffer.
-func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte {
+func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte {
 	return genericFtoa(dst, f, fmt, prec, bitSize)
 }
 
@@ -418,39 +418,27 @@
 	return dst
 }
 
-// %b: -ddddddddp+ddd
+// %b: -ddddddddp±ddd
 func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte {
-	var buf [50]byte
-	w := len(buf)
-	exp -= int(flt.mantbits)
-	esign := byte('+')
-	if exp < 0 {
-		esign = '-'
-		exp = -exp
-	}
-	n := 0
-	for exp > 0 || n < 1 {
-		n++
-		w--
-		buf[w] = byte(exp%10 + '0')
-		exp /= 10
-	}
-	w--
-	buf[w] = esign
-	w--
-	buf[w] = 'p'
-	n = 0
-	for mant > 0 || n < 1 {
-		n++
-		w--
-		buf[w] = byte(mant%10 + '0')
-		mant /= 10
-	}
+	// sign
 	if neg {
-		w--
-		buf[w] = '-'
+		dst = append(dst, '-')
 	}
-	return append(dst, buf[w:]...)
+
+	// mantissa
+	dst, _ = formatBits(dst, mant, 10, false, true)
+
+	// p
+	dst = append(dst, 'p')
+
+	// ±exponent
+	exp -= int(flt.mantbits)
+	if exp >= 0 {
+		dst = append(dst, '+')
+	}
+	dst, _ = formatBits(dst, uint64(exp), 10, exp < 0, true)
+
+	return dst
 }
 
 func min(a, b int) int {
diff --git a/src/strconv/ftoa_test.go b/src/strconv/ftoa_test.go
index 39b8615..1b4dcd9 100644
--- a/src/strconv/ftoa_test.go
+++ b/src/strconv/ftoa_test.go
@@ -227,6 +227,7 @@
 func BenchmarkAppendFloatBig(b *testing.B) {
 	benchmarkAppendFloat(b, 123456789123456789123456789, 'g', -1, 64)
 }
+func BenchmarkAppendFloatBinaryExp(b *testing.B) { benchmarkAppendFloat(b, -1, 'b', -1, 64) }
 
 func BenchmarkAppendFloat32Integer(b *testing.B)       { benchmarkAppendFloat(b, 33909, 'g', -1, 32) }
 func BenchmarkAppendFloat32ExactFraction(b *testing.B) { benchmarkAppendFloat(b, 3.375, 'g', -1, 32) }