conv/float.go (96 lines of code) (raw):

package conv import ( "math" "strconv" ) const maxEligbleInt64 = math.MaxInt64 - 512 const minEligbleInt64 = math.MinInt64 + 513 // Float64ToBytes is an optimized implementation for converting float64 to byte array func Float64ToBytes(n float64, prec int, buf *[39]byte) []byte { if n != n { return NaNb } if n == 0 { if prec > 0 { if prec < 18 { return float0[prec] } } else { return float0[0] } } else { if n <= maxEligbleInt64 && n >= minEligbleInt64 && prec < 18 && prec >= 0 { return f64Dig(n, prec, buf) } } return []byte(strconv.FormatFloat(n, 'f', prec, 64)) } // Float64ToString is an optimized implementation for converting float64 to string func Float64ToString(n float64, prec int, buf *[39]byte) string { if n != n { return NaN } if n == 0 { if prec > 0 { if prec < 18 { return float0s[prec] } } else { return float0s[0] } } else { if n <= maxEligbleInt64 && n >= minEligbleInt64 && prec < 18 && prec >= 0 { return string(f64Dig(n, prec, buf)) } } return strconv.FormatFloat(n, 'f', prec, 64) } func f64Dig(n float64, prec int, buf *[39]byte) []byte { neg := n < 0 if neg { n = -n } u := int64(n) l := n - float64(u) var ul uint64 if l+math.Pow10(-prec)/2 >= 1 { u++ ul = 0 l = 0 } else { ul = uint64(math.Round((n - float64(u)) * math.Pow10(prec))) } pos := 20 for u >= 100 { pos -= 2 is := u % 100 u /= 100 buf[pos+1], buf[pos] = digits2[is][1], digits2[is][0] } if u < 10 { pos-- buf[pos] = digits[u] } else { pos -= 2 buf[pos+1], buf[pos] = digits2[u][1], digits2[u][0] } if neg { pos-- buf[pos] = '-' } if prec == 0 { return buf[pos:20] } ed := 20 + prec buf[20] = '.' for ed > 20 { is := ul % 100 ul /= 100 if ed == 21 { buf[ed] = digits[is] break } else { buf[ed], buf[ed-1] = digits2[is][1], digits2[is][0] ed -= 2 } } return buf[pos : 21+prec] }