From 448c05d7c8f559e3d8ea0b75b57bff5178e38704 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 30 Nov 2010 12:53:42 -0800 Subject: [PATCH] strconv: Atof on Infs and NaNs R=rsc CC=golang-dev https://golang.org/cl/3359041 --- src/pkg/strconv/atof.go | 42 ++++++++++++++++++++++++++++++++++++ src/pkg/strconv/atof_test.go | 10 +++++++++ 2 files changed, 52 insertions(+) diff --git a/src/pkg/strconv/atof.go b/src/pkg/strconv/atof.go index 262a8b53c7..90ca7c4f9c 100644 --- a/src/pkg/strconv/atof.go +++ b/src/pkg/strconv/atof.go @@ -19,6 +19,40 @@ import ( var optimize = true // can change for testing +func equalIgnoreCase(s1, s2 string) bool { + if len(s1) != len(s2) { + return false + } + for i := 0; i < len(s1); i++ { + c1 := s1[i] + if 'A' <= c1 && c1 <= 'Z' { + c1 += 'a' - 'A' + } + c2 := s2[i] + if 'A' <= c2 && c2 <= 'Z' { + c2 += 'a' - 'A' + } + if c1 != c2 { + return false + } + } + return true +} + +func special(s string) (f float64, ok bool) { + switch { + case equalIgnoreCase(s, "nan"): + return math.NaN(), true + case equalIgnoreCase(s, "-inf"): + return math.Inf(-1), true + case equalIgnoreCase(s, "+inf"): + return math.Inf(1), true + case equalIgnoreCase(s, "inf"): + return math.Inf(1), true + } + return +} + // TODO(rsc): Better truncation handling. func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) { i := 0 @@ -320,6 +354,10 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) { // away from the largest floating point number of the given size, // Atof32 returns f = ±Inf, err.Error = os.ERANGE. func Atof32(s string) (f float32, err os.Error) { + if val, ok := special(s); ok { + return float32(val), nil + } + neg, d, trunc, ok := stringToDecimal(s) if !ok { return 0, &NumError{s, os.EINVAL} @@ -341,6 +379,10 @@ func Atof32(s string) (f float32, err os.Error) { // Except for the type of its result, its definition is the same as that // of Atof32. func Atof64(s string) (f float64, err os.Error) { + if val, ok := special(s); ok { + return val, nil + } + neg, d, trunc, ok := stringToDecimal(s) if !ok { return 0, &NumError{s, os.EINVAL} diff --git a/src/pkg/strconv/atof_test.go b/src/pkg/strconv/atof_test.go index 1f7543891f..2277ff61a6 100644 --- a/src/pkg/strconv/atof_test.go +++ b/src/pkg/strconv/atof_test.go @@ -37,6 +37,16 @@ var atoftests = []atofTest{ {"1e-20", "1e-20", nil}, {"625e-3", "0.625", nil}, + // NaNs + {"nan", "NaN", nil}, + {"NaN", "NaN", nil}, + {"NAN", "NaN", nil}, + + // Infs + {"inf", "+Inf", nil}, + {"-Inf", "-Inf", nil}, + {"+INF", "+Inf", nil}, + // largest float64 {"1.7976931348623157e308", "1.7976931348623157e+308", nil}, {"-1.7976931348623157e308", "-1.7976931348623157e+308", nil}, -- 2.50.0