diff options
Diffstat (limited to 'src/pkg/strconv/atof.go')
-rw-r--r-- | src/pkg/strconv/atof.go | 87 |
1 files changed, 53 insertions, 34 deletions
diff --git a/src/pkg/strconv/atof.go b/src/pkg/strconv/atof.go index 86c56f7fd..42fc431db 100644 --- a/src/pkg/strconv/atof.go +++ b/src/pkg/strconv/atof.go @@ -12,10 +12,7 @@ package strconv // 2) Multiply/divide decimal by powers of two until in range [0.5, 1) // 3) Multiply by 2^precision and round to get mantissa. -import ( - "math" - "os" -) +import "math" var optimize = true // can change for testing @@ -266,6 +263,18 @@ func (d *decimal) atof32int() float32 { return f } +// Reads a uint64 decimal mantissa, which might be truncated. +func (d *decimal) atou64() (mant uint64, digits int) { + const uint64digits = 19 + for i, c := range d.d[:d.nd] { + if i == uint64digits { + return mant, i + } + mant = 10*mant + uint64(c-'0') + } + return mant, d.nd +} + // Exact powers of 10. var float64pow10 = []float64{ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, @@ -341,28 +350,16 @@ func (d *decimal) atof32() (f float32, ok bool) { return } -// Atof32 converts the string s to a 32-bit floating-point number. -// -// If s is well-formed and near a valid floating point number, -// Atof32 returns the nearest floating point number rounded -// using IEEE754 unbiased rounding. -// -// The errors that Atof32 returns have concrete type *NumError -// and include err.Num = s. -// -// If s is not syntactically well-formed, Atof32 returns err.Error = os.EINVAL. -// -// If s is syntactically well-formed but is more than 1/2 ULP -// 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) { +const fnParseFloat = "ParseFloat" + +func atof32(s string) (f float32, err error) { if val, ok := special(s); ok { return float32(val), nil } var d decimal if !d.set(s) { - return 0, &NumError{s, os.EINVAL} + return 0, syntaxError(fnParseFloat, s) } if optimize { if f, ok := d.atof32(); ok { @@ -372,44 +369,66 @@ func Atof32(s string) (f float32, err os.Error) { b, ovf := d.floatBits(&float32info) f = math.Float32frombits(uint32(b)) if ovf { - err = &NumError{s, os.ERANGE} + err = rangeError(fnParseFloat, s) } return f, err } -// Atof64 converts the string s to a 64-bit floating-point number. -// 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) { +func atof64(s string) (f float64, err error) { if val, ok := special(s); ok { return val, nil } var d decimal if !d.set(s) { - return 0, &NumError{s, os.EINVAL} + return 0, syntaxError(fnParseFloat, s) } if optimize { if f, ok := d.atof64(); ok { return f, nil } + + // Try another fast path. + ext := new(extFloat) + if ok := ext.AssignDecimal(&d); ok { + b, ovf := ext.floatBits() + f = math.Float64frombits(b) + if ovf { + err = rangeError(fnParseFloat, s) + } + return f, err + } } b, ovf := d.floatBits(&float64info) f = math.Float64frombits(b) if ovf { - err = &NumError{s, os.ERANGE} + err = rangeError(fnParseFloat, s) } return f, err } -// AtofN converts the string s to a 64-bit floating-point number, -// but it rounds the result assuming that it will be stored in a value -// of n bits (32 or 64). -func AtofN(s string, n int) (f float64, err os.Error) { - if n == 32 { - f1, err1 := Atof32(s) +// ParseFloat converts the string s to a floating-point number +// with the precision specified by bitSize: 32 for float32, or 64 for float64. +// When bitSize=32, the result still has type float64, but it will be +// convertible to float32 without changing its value. +// +// If s is well-formed and near a valid floating point number, +// ParseFloat returns the nearest floating point number rounded +// using IEEE754 unbiased rounding. +// +// The errors that ParseFloat returns have concrete type *NumError +// and include err.Num = s. +// +// If s is not syntactically well-formed, ParseFloat returns err.Error = ErrSyntax. +// +// If s is syntactically well-formed but is more than 1/2 ULP +// away from the largest floating point number of the given size, +// ParseFloat returns f = ±Inf, err.Error = ErrRange. +func ParseFloat(s string, bitSize int) (f float64, err error) { + if bitSize == 32 { + f1, err1 := atof32(s) return float64(f1), err1 } - f1, err1 := Atof64(s) + f1, err1 := atof64(s) return f1, err1 } |