strconv: simplified logic resulting in faster float formatting
benchmark old ns/op new ns/op delta
BenchmarkFormatFloatDecimal 300 283 -5.67%
BenchmarkFormatFloat 383 381 -0.52%
BenchmarkFormatFloatExp 359 357 -0.56%
BenchmarkFormatFloatNegExp 357 358 +0.28%
BenchmarkFormatFloatBig 468 430 -8.12%
BenchmarkAppendFloatDecimal 104 92.5 -11.06%
BenchmarkAppendFloat 199 190 -4.52%
BenchmarkAppendFloatExp 172 167 -2.91%
BenchmarkAppendFloatNegExp 172 169 -1.74%
BenchmarkAppendFloatBig 280 235 -16.07%
BenchmarkAppendFloat32Integer 104 92.4 -11.15%
BenchmarkAppendFloat32ExactFraction 168 171 +1.79%
BenchmarkAppendFloat32Point 206 199 -3.40%
BenchmarkAppendFloat32Exp 167 167 +0.00%
BenchmarkAppendFloat32NegExp 167 166 -0.60%
BenchmarkAppendFloat64Fixed1 134 129 -3.73%
BenchmarkAppendFloat64Fixed2 144 136 -5.56%
BenchmarkAppendFloat64Fixed3 138 134 -2.90%
BenchmarkAppendFloat64Fixed4 145 138 -4.83%
Change-Id: Ia143840cb34cbd1cebd6b691dd0a45b7264b406c
Reviewed-on: https://go-review.googlesource.com/3920
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go
index 1a9c41b..f885d96 100644
--- a/src/strconv/ftoa.go
+++ b/src/strconv/ftoa.go
@@ -119,7 +119,7 @@
// Precision for shortest representation mode.
switch fmt {
case 'e', 'E':
- prec = digs.nd - 1
+ prec = max(digs.nd-1, 0)
case 'f':
prec = max(digs.nd-digs.dp, 0)
case 'g', 'G':
@@ -348,14 +348,13 @@
if prec > 0 {
dst = append(dst, '.')
i := 1
- m := d.nd + prec + 1 - max(d.nd, prec+1)
- for i < m {
- dst = append(dst, d.d[i])
- i++
+ m := min(d.nd, prec+1)
+ if i < m {
+ dst = append(dst, d.d[i:m]...)
+ i = m
}
- for i <= prec {
+ for ; i <= prec; i++ {
dst = append(dst, '0')
- i++
}
}
@@ -373,27 +372,16 @@
}
dst = append(dst, ch)
- // dddd
- var buf [3]byte
- i := len(buf)
- for exp >= 10 {
- i--
- buf[i] = byte(exp%10 + '0')
- exp /= 10
+ // dd or ddd
+ switch {
+ case exp < 10:
+ dst = append(dst, '0', byte(exp)+'0')
+ case exp < 100:
+ dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0')
+ default:
+ dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0')
}
- // exp < 10
- i--
- buf[i] = byte(exp + '0')
- switch i {
- case 0:
- dst = append(dst, buf[0], buf[1], buf[2])
- case 1:
- dst = append(dst, buf[1], buf[2])
- case 2:
- // leading zeroes
- dst = append(dst, '0', buf[2])
- }
return dst
}
@@ -406,11 +394,9 @@
// integer, padded with zeros as needed.
if d.dp > 0 {
- var i int
- for i = 0; i < d.dp && i < d.nd; i++ {
- dst = append(dst, d.d[i])
- }
- for ; i < d.dp; i++ {
+ m := min(d.nd, d.dp)
+ dst = append(dst, d.d[:m]...)
+ for ; m < d.dp; m++ {
dst = append(dst, '0')
}
} else {
@@ -467,6 +453,13 @@
return append(dst, buf[w:]...)
}
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
func max(a, b int) int {
if a > b {
return a