1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements rat-to-string conversion functions.
17 func ratTok(ch rune) bool {
18 return strings.IndexRune("+-/0123456789.eE", ch) >= 0
21 // Scan is a support routine for fmt.Scanner. It accepts the formats
22 // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
23 func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
24 tok, err := s.Token(true, ratTok)
28 if strings.IndexRune("efgEFGv", ch) < 0 {
29 return errors.New("Rat.Scan: invalid verb")
31 if _, ok := z.SetString(string(tok)); !ok {
32 return errors.New("Rat.Scan: invalid syntax")
37 // SetString sets z to the value of s and returns z and a boolean indicating
38 // success. s can be given as a fraction "a/b" or as a floating-point number
39 // optionally followed by an exponent. If the operation failed, the value of
40 // z is undefined but the returned value is nil.
41 func (z *Rat) SetString(s string) (*Rat, bool) {
47 // parse fraction a/b, if any
48 if sep := strings.Index(s, "/"); sep >= 0 {
49 if _, ok := z.a.SetString(s[:sep], 0); !ok {
54 if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
57 if len(z.b.abs) == 0 {
63 // parse floating-point number
64 r := strings.NewReader(s)
67 neg, err := scanSign(r)
74 z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
82 exp, ebase, err = scanExponent(r)
83 if ebase == 2 || err != nil {
87 // there should be no unread characters left
88 if _, err = r.ReadByte(); err != io.EOF {
97 // compute exponent power
102 powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
109 z.a.abs = z.a.abs.mul(z.a.abs, powTen)
110 z.b.abs = z.b.abs[:0]
113 z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
118 func scanExponent(r io.ByteScanner) (exp int64, base int, err error) {
122 if ch, err = r.ReadByte(); err != nil {
124 err = nil // no exponent; same as e0
136 return // no exponent; same as e0
140 if neg, err = scanSign(r); err != nil {
146 digits = append(digits, '-')
149 // no need to use nat.scan for exponent digits
150 // since we only care about int64 values - the
151 // from-scratch scan is easy enough and faster
153 if ch, err = r.ReadByte(); err != nil {
154 if err != io.EOF || i == 0 {
160 if ch < '0' || '9' < ch {
163 err = fmt.Errorf("invalid exponent (missing digits)")
168 digits = append(digits, byte(ch))
170 // i > 0 => we have at least one digit
172 exp, err = strconv.ParseInt(string(digits), 10, 64)
176 // String returns a string representation of x in the form "a/b" (even if b == 1).
177 func (x *Rat) String() string {
179 if len(x.b.abs) != 0 {
180 s = "/" + x.b.abs.decimalString()
182 return x.a.String() + s
185 // RatString returns a string representation of x in the form "a/b" if b != 1,
186 // and in the form "a" if b == 1.
187 func (x *Rat) RatString() string {
194 // FloatString returns a string representation of x in decimal form with prec
195 // digits of precision after the decimal point and the last digit rounded.
196 func (x *Rat) FloatString(prec int) string {
200 s += "." + strings.Repeat("0", prec)
206 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
210 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
214 r, r2 := r.div(nat(nil), r, x.b.abs)
216 // see if we need to round up
218 if x.b.abs.cmp(r2) <= 0 {
221 q = nat(nil).add(q, natOne)
222 r = nat(nil).sub(r, p)
226 s := q.decimalString()
232 rs := r.decimalString()
233 leadingZeros := prec - len(rs)
234 s += "." + strings.Repeat("0", leadingZeros) + rs