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 big
import (
)
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 [Float.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) {
:= .prec
if == 0 {
= 64
}
// A reasonable value in case of an error.
.form = zero
// sign
.neg, = scanSign()
if != nil {
return
}
// mantissa
var int // fractional digit count; valid if <= 0
.mant, , , = .mant.scan(, , true)
if != nil {
return
}
// exponent
var int64
var int
, , = scanExponent(, true, == 0)
if != nil {
return
}
// special-case 0
if 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 point
if < 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**e
case 2:
+=
case 8:
+= * 3 // octal digits are 3 bits each
case 16:
+= * 4 // hexadecimal digits are 4 bits each
default:
panic("unexpected mantissa base")
}
// fcount consumed - not needed anymore
}
// take actual exponent into account
switch {
case 10:
+=
fallthrough // see fallthrough above
case 2:
+=
default:
panic("unexpected exponent base")
}
// exp consumed - not needed anymore
// apply 2**exp2
if 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 than 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 ±Inf
if 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 consumed
if , := .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
}
The pages are generated with Golds v0.7.0-preview. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |