123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- // Copyright 2015 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // This file implements string-to-Float conversion functions.
- package big
- import (
- "fmt"
- "io"
- "strings"
- )
- var floatZero Float
- // SetString sets z to the value of s and returns z and a boolean indicating
- // success. s must be a floating-point number of the same format as accepted
- // by Parse, with base argument 0. The entire string (not just a prefix) must
- // be valid for success. If the operation failed, the value of z is undefined
- // but the returned value is nil.
- func (z *Float) SetString(s string) (*Float, bool) {
- if f, _, err := z.Parse(s, 0); err == nil {
- return f, true
- }
- return nil, false
- }
- // scan is like Parse but reads the longest possible prefix representing a valid
- // floating point number from an io.ByteScanner rather than a string. It serves
- // as the implementation of Parse. It does not recognize ±Inf and does not expect
- // EOF at the end.
- func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
- prec := z.prec
- if prec == 0 {
- prec = 64
- }
- // A reasonable value in case of an error.
- z.form = zero
- // sign
- z.neg, err = scanSign(r)
- if err != nil {
- return
- }
- // mantissa
- var fcount int // fractional digit count; valid if <= 0
- z.mant, b, fcount, err = z.mant.scan(r, base, true)
- if err != nil {
- return
- }
- // exponent
- var exp int64
- var ebase int
- exp, ebase, err = scanExponent(r, true, base == 0)
- if err != nil {
- return
- }
- // special-case 0
- if len(z.mant) == 0 {
- z.prec = prec
- z.acc = Exact
- z.form = zero
- f = z
- return
- }
- // len(z.mant) > 0
- // The mantissa may have a radix point (fcount <= 0) and there
- // may be a nonzero exponent exp. The radix point amounts to a
- // division by b**(-fcount). An exponent means multiplication by
- // ebase**exp. Finally, mantissa normalization (shift left) requires
- // a correcting multiplication by 2**(-shiftcount). Multiplications
- // are commutative, so we can apply them in any order as long as there
- // is no loss of precision. We only have powers of 2 and 10, and
- // we split powers of 10 into the product of the same powers of
- // 2 and 5. This reduces the size of the multiplication factor
- // needed for base-10 exponents.
- // normalize mantissa and determine initial exponent contributions
- exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
- exp5 := int64(0)
- // determine binary or decimal exponent contribution of radix point
- if fcount < 0 {
- // The mantissa has a radix point ddd.dddd; and
- // -fcount is the number of digits to the right
- // of '.'. Adjust relevant exponent accordingly.
- d := int64(fcount)
- switch b {
- case 10:
- exp5 = d
- fallthrough // 10**e == 5**e * 2**e
- case 2:
- exp2 += d
- case 8:
- exp2 += d * 3 // octal digits are 3 bits each
- case 16:
- exp2 += d * 4 // hexadecimal digits are 4 bits each
- default:
- panic("unexpected mantissa base")
- }
- // fcount consumed - not needed anymore
- }
- // take actual exponent into account
- switch ebase {
- case 10:
- exp5 += exp
- fallthrough // see fallthrough above
- case 2:
- exp2 += exp
- default:
- panic("unexpected exponent base")
- }
- // exp consumed - not needed anymore
- // apply 2**exp2
- if MinExp <= exp2 && exp2 <= MaxExp {
- z.prec = prec
- z.form = finite
- z.exp = int32(exp2)
- f = z
- } else {
- err = fmt.Errorf("exponent overflow")
- return
- }
- if exp5 == 0 {
- // no decimal exponent contribution
- z.round(0)
- return
- }
- // exp5 != 0
- // apply 5**exp5
- p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
- if exp5 < 0 {
- z.Quo(z, p.pow5(uint64(-exp5)))
- } else {
- z.Mul(z, p.pow5(uint64(exp5)))
- }
- return
- }
- // These powers of 5 fit into a uint64.
- //
- // for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
- // fmt.Println(q)
- // }
- //
- var pow5tab = [...]uint64{
- 1,
- 5,
- 25,
- 125,
- 625,
- 3125,
- 15625,
- 78125,
- 390625,
- 1953125,
- 9765625,
- 48828125,
- 244140625,
- 1220703125,
- 6103515625,
- 30517578125,
- 152587890625,
- 762939453125,
- 3814697265625,
- 19073486328125,
- 95367431640625,
- 476837158203125,
- 2384185791015625,
- 11920928955078125,
- 59604644775390625,
- 298023223876953125,
- 1490116119384765625,
- 7450580596923828125,
- }
- // pow5 sets z to 5**n and returns z.
- // n must not be negative.
- func (z *Float) pow5(n uint64) *Float {
- const m = uint64(len(pow5tab) - 1)
- if n <= m {
- return z.SetUint64(pow5tab[n])
- }
- // n > m
- z.SetUint64(pow5tab[m])
- n -= m
- // use more bits for f than for z
- // TODO(gri) what is the right number?
- f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
- for n > 0 {
- if n&1 != 0 {
- z.Mul(z, f)
- }
- f.Mul(f, f)
- n >>= 1
- }
- return z
- }
- // Parse parses s which must contain a text representation of a floating-
- // point number with a mantissa in the given conversion base (the exponent
- // is always a decimal number), or a string representing an infinite value.
- //
- // For base 0, an underscore character ``_'' may appear between a base
- // prefix and an adjacent digit, and between successive digits; such
- // underscores do not change the value of the number, or the returned
- // digit count. Incorrect placement of underscores is reported as an
- // error if there are no other errors. If base != 0, underscores are
- // not recognized and thus terminate scanning like any other character
- // that is not a valid radix point or digit.
- //
- // It sets z to the (possibly rounded) value of the corresponding floating-
- // point value, and returns z, the actual base b, and an error err, if any.
- // The entire string (not just a prefix) must be consumed for success.
- // If z's precision is 0, it is changed to 64 before rounding takes effect.
- // The number must be of the form:
- //
- // number = [ sign ] ( float | "inf" | "Inf" ) .
- // sign = "+" | "-" .
- // float = ( mantissa | prefix pmantissa ) [ exponent ] .
- // prefix = "0" [ "b" | "B" | "o" | "O" | "x" | "X" ] .
- // mantissa = digits "." [ digits ] | digits | "." digits .
- // pmantissa = [ "_" ] digits "." [ digits ] | [ "_" ] digits | "." digits .
- // exponent = ( "e" | "E" | "p" | "P" ) [ sign ] digits .
- // digits = digit { [ "_" ] digit } .
- // digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
- //
- // The base argument must be 0, 2, 8, 10, or 16. Providing an invalid base
- // argument will lead to a run-time panic.
- //
- // For base 0, the number prefix determines the actual base: A prefix of
- // ``0b'' or ``0B'' selects base 2, ``0o'' or ``0O'' selects base 8, and
- // ``0x'' or ``0X'' selects base 16. Otherwise, the actual base is 10 and
- // no prefix is accepted. The octal prefix "0" is not supported (a leading
- // "0" is simply considered a "0").
- //
- // A "p" or "P" exponent indicates a base 2 (rather then base 10) exponent;
- // for instance, "0x1.fffffffffffffp1023" (using base 0) represents the
- // maximum float64 value. For hexadecimal mantissae, the exponent character
- // must be one of 'p' or 'P', if present (an "e" or "E" exponent indicator
- // cannot be distinguished from a mantissa digit).
- //
- // The returned *Float f is nil and the value of z is valid but not
- // defined if an error is reported.
- //
- func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
- // scan doesn't handle ±Inf
- if len(s) == 3 && (s == "Inf" || s == "inf") {
- f = z.SetInf(false)
- return
- }
- if len(s) == 4 && (s[0] == '+' || s[0] == '-') && (s[1:] == "Inf" || s[1:] == "inf") {
- f = z.SetInf(s[0] == '-')
- return
- }
- r := strings.NewReader(s)
- if f, b, err = z.scan(r, base); err != nil {
- return
- }
- // entire string must have been consumed
- if ch, err2 := r.ReadByte(); err2 == nil {
- err = fmt.Errorf("expected end of string, found %q", ch)
- } else if err2 != io.EOF {
- err = err2
- }
- return
- }
- // ParseFloat is like f.Parse(s, base) with f set to the given precision
- // and rounding mode.
- func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
- return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
- }
- var _ fmt.Scanner = (*Float)(nil) // *Float must implement fmt.Scanner
- // Scan is a support routine for fmt.Scanner; it sets z to the value of
- // the scanned number. It accepts formats whose verbs are supported by
- // fmt.Scan for floating point values, which are:
- // 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'.
- // Scan doesn't handle ±Inf.
- func (z *Float) Scan(s fmt.ScanState, ch rune) error {
- s.SkipSpace()
- _, _, err := z.scan(byteReader{s}, 0)
- return err
- }
|