From 37cd1658386bcc1d4f4ffddb30dd863df2e2ce7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Oudompheng?= Date: Thu, 12 Jan 2012 11:34:06 -0800 Subject: [PATCH] strconv: implement fast path for rounding already short numbers. benchmark old ns/op new ns/op delta BenchmarkFormatFloatDecimal 3765 1386 -63% R=rsc CC=golang-dev, remy https://golang.org/cl/5494060 --- src/pkg/strconv/ftoa.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/pkg/strconv/ftoa.go b/src/pkg/strconv/ftoa.go index b1d4b32f03e..ab8dd2bf952 100644 --- a/src/pkg/strconv/ftoa.go +++ b/src/pkg/strconv/ftoa.go @@ -178,15 +178,26 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { return } - // TODO(rsc): Unless exp == minexp, if the number of digits in d - // is less than 17, it seems likely that it would be - // the shortest possible number already. So maybe we can - // bail out without doing the extra multiprecision math here. - // Compute upper and lower such that any decimal number // between upper and lower (possibly inclusive) // will round to the original floating point number. + // We may see at once that the number is already shortest. + // + // Suppose d is not denormal, so that 2^exp <= d < 10^dp. + // The closest shorter number is at least 10^(dp-nd) away. + // The lower/upper bounds computed below are at distance + // at most 2^(exp-mantbits). + // + // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), + // or equivalently log2(10)*(dp-nd) > exp-mantbits. + // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). + minexp := flt.bias + 1 // minimum possible exponent + if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { + // The number is already shortest. + return + } + // d = mant << (exp - mantbits) // Next highest floating point number is mant+1 << exp-mantbits. // Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1. @@ -200,7 +211,6 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { // in which case the next lowest is mant*2-1 << exp-mantbits-1. // Either way, call it mantlo << explo-mantbits. // Our lower bound is halfway inbetween, mantlo*2+1 << explo-mantbits-1. - minexp := flt.bias + 1 // minimum possible exponent var mantlo uint64 var explo int if mant > 1<