diff options
author | Rob Pike <r@golang.org> | 2010-11-30 12:53:42 -0800 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2010-11-30 12:53:42 -0800 |
commit | 448c05d7c8f559e3d8ea0b75b57bff5178e38704 (patch) | |
tree | 2738f84ac584a75d29d7215ed98ed406200ae072 | |
parent | b3896462435fde33f20b36131e4a94f61a9fe803 (diff) | |
download | go-448c05d7c8f559e3d8ea0b75b57bff5178e38704.tar.gz go-448c05d7c8f559e3d8ea0b75b57bff5178e38704.zip |
strconv: Atof on Infs and NaNs
R=rsc
CC=golang-dev
https://golang.org/cl/3359041
-rw-r--r-- | src/pkg/strconv/atof.go | 42 | ||||
-rw-r--r-- | src/pkg/strconv/atof_test.go | 10 |
2 files changed, 52 insertions, 0 deletions
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}, |