Source File
floatconv.go
Belonging Package
math/big
// 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 bigimport ()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 ( *Float) ( string) (*Float, bool) {if , , := .Parse(, 0); == nil {return , 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 ( *Float) ( io.ByteScanner, int) ( *Float, int, error) {:= .precif == 0 {= 64}// A reasonable value in case of an error..form = zero// sign.neg, = scanSign()if != nil {return}// mantissavar int // fractional digit count; valid if <= 0.mant, , , = .mant.scan(, , true)if != nil {return}// exponentvar int64var int, , = scanExponent(, true, == 0)if != nil {return}// special-case 0if len(.mant) == 0 {.prec =.acc = Exact.form = zero=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:= int64(len(.mant))*_W - fnorm(.mant):= int64(0)// determine binary or decimal exponent contribution of radix pointif < 0 {// The mantissa has a radix point ddd.dddd; and// -fcount is the number of digits to the right// of '.'. Adjust relevant exponent accordingly.:= int64()switch {case 10:=fallthrough // 10**e == 5**e * 2**ecase 2:+=case 8:+= * 3 // octal digits are 3 bits eachcase 16:+= * 4 // hexadecimal digits are 4 bits eachdefault:panic("unexpected mantissa base")}// fcount consumed - not needed anymore}// take actual exponent into accountswitch {case 10:+=fallthrough // see fallthrough abovecase 2:+=default:panic("unexpected exponent base")}// exp consumed - not needed anymore// apply 2**exp2if MinExp <= && <= MaxExp {.prec =.form = finite.exp = int32()=} else {= fmt.Errorf("exponent overflow")return}if == 0 {// no decimal exponent contribution.round(0)return}// exp5 != 0// apply 5**exp5:= new(Float).SetPrec(.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?if < 0 {.Quo(, .pow5(uint64(-)))} else {.Mul(, .pow5(uint64()))}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 ( *Float) ( uint64) *Float {const = uint64(len(pow5tab) - 1)if <= {return .SetUint64(pow5tab[])}// n > m.SetUint64(pow5tab[])-=// use more bits for f than for z// TODO(gri) what is the right number?:= new(Float).SetPrec(.Prec() + 64).SetUint64(5)for > 0 {if &1 != 0 {.Mul(, )}.Mul(, )>>= 1}return}// 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 ( *Float) ( string, int) ( *Float, int, error) {// scan doesn't handle ±Infif len() == 3 && ( == "Inf" || == "inf") {= .SetInf(false)return}if len() == 4 && ([0] == '+' || [0] == '-') && ([1:] == "Inf" || [1:] == "inf") {= .SetInf([0] == '-')return}:= strings.NewReader()if , , = .scan(, ); != nil {return}// entire string must have been consumedif , := .ReadByte(); == nil {= fmt.Errorf("expected end of string, found %q", )} else if != io.EOF {=}return}// ParseFloat is like f.Parse(s, base) with f set to the given precision// and rounding mode.func ( string, int, uint, RoundingMode) ( *Float, int, error) {return new(Float).SetPrec().SetMode().Parse(, )}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 ( *Float) ( fmt.ScanState, rune) error {.SkipSpace(), , := .scan(byteReader{}, 0)return}