pkg/eval/vals: Print floats with exponents between -4 and 13 with %f.

This fixes #811.
This commit is contained in:
Qi Xiao 2020-01-12 10:28:31 -05:00
parent 4fb04bc27a
commit 9ad6eba476
2 changed files with 26 additions and 2 deletions

View File

@ -1,6 +1,9 @@
package vals package vals
import "strconv" import (
"strconv"
"strings"
)
// Stringer wraps the String method. // Stringer wraps the String method.
type Stringer interface { type Stringer interface {
@ -25,5 +28,18 @@ func ToString(v interface{}) string {
} }
func formatFloat64(f float64) string { func formatFloat64(f float64) string {
return strconv.FormatFloat(f, 'g', -1, 64) // Go's 'g' format is almost what we want, except that its threshold for
// "large exponent" is too low - 6 for positive exponents and -5 for
// negative exponents. This means that relative small numbers like 1234567
// are printed with scientific notations, something we don't really want.
// See also b.elv.sh/811.
//
// So we emulate the 'g' format by first using 'f', parse the result, and
// use 'e' if the exponent >= 14 or <= -5.
s := strconv.FormatFloat(f, 'f', -1, 64)
i := strings.IndexByte(s, '.')
if (i == -1 && len(s) > 14) || i >= 14 || strings.HasPrefix(s, "0.0000") {
return strconv.FormatFloat(f, 'e', -1, 64)
}
return s
} }

View File

@ -11,9 +11,17 @@ func TestToString(t *testing.T) {
Test(t, Fn("ToString", ToString), Table{ Test(t, Fn("ToString", ToString), Table{
// string // string
Args("a").Rets("a"), Args("a").Rets("a"),
// float64 // float64
Args(42.0).Rets("42"), Args(42.0).Rets("42"),
Args(0.1).Rets("0.1"), Args(0.1).Rets("0.1"),
// Exponents >= 14 are printed in scientific notation.
Args(1e13).Rets("10000000000000"),
Args(1e14).Rets("1e+14"),
// Exponents <= -5 are printed in scientific notation.
Args(1e-4).Rets("0.0001"),
Args(1e-5).Rets("1e-05"),
// Stringer // Stringer
Args(bytes.NewBufferString("buffer")).Rets("buffer"), Args(bytes.NewBufferString("buffer")).Rets("buffer"),
// None of the above: delegate to Repr // None of the above: delegate to Repr