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.ContainsRune("+-/0123456789.eE", ch)
22 var _ fmt.Scanner = &ratZero // *Rat must implement fmt.Scanner
24 // Scan is a support routine for fmt.Scanner. It accepts the formats
25 // 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
26 func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
27 tok, err := s.Token(true, ratTok)
31 if !strings.ContainsRune("efgEFGv", ch) {
32 return errors.New("Rat.Scan: invalid verb")
34 if _, ok := z.SetString(string(tok)); !ok {
35 return errors.New("Rat.Scan: invalid syntax")
40 // SetString sets z to the value of s and returns z and a boolean indicating
41 // success. s can be given as a fraction "a/b" or as a decimal floating-point
42 // number optionally followed by an exponent. The entire string (not just a prefix)
43 // must be valid for success. If the operation failed, the value of z is
44 // undefined but the returned value is nil.
45 func (z *Rat) SetString(s string) (*Rat, bool) {
51 // parse fraction a/b, if any
52 if sep := strings.Index(s, "/"); sep >= 0 {
53 if _, ok := z.a.SetString(s[:sep], 0); !ok {
56 r := strings.NewReader(s[sep+1:])
58 if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
61 // entire string must have been consumed
62 if _, err = r.ReadByte(); err != io.EOF {
65 if len(z.b.abs) == 0 {
71 // parse floating-point number
72 r := strings.NewReader(s)
75 neg, err := scanSign(r)
81 // TODO(gri) allow other bases besides 10 for mantissa and exponent? (issue #29799)
83 z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
90 exp, _, err = scanExponent(r, false, false)
95 // there should be no unread characters left
96 if _, err = r.ReadByte(); err != io.EOF {
100 // special-case 0 (see also issue #16176)
101 if len(z.a.abs) == 0 {
111 // compute exponent power
116 powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
123 z.a.abs = z.a.abs.mul(z.a.abs, powTen)
124 z.b.abs = z.b.abs[:0]
127 z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
132 // scanExponent scans the longest possible prefix of r representing a base 10
133 // (``e'', ``E'') or a base 2 (``p'', ``P'') exponent, if any. It returns the
134 // exponent, the exponent base (10 or 2), or a read or syntax error, if any.
136 // If sepOk is set, an underscore character ``_'' may appear between successive
137 // exponent digits; such underscores do not change the value of the exponent.
138 // Incorrect placement of underscores is reported as an error if there are no
139 // other errors. If sepOk is not set, underscores are not recognized and thus
140 // terminate scanning like any other character that is not a valid digit.
142 // exponent = ( "e" | "E" | "p" | "P" ) [ sign ] digits .
143 // sign = "+" | "-" .
144 // digits = digit { [ '_' ] digit } .
145 // digit = "0" ... "9" .
147 // A base 2 exponent is only permitted if base2ok is set.
148 func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, err error) {
149 // one char look-ahead
150 ch, err := r.ReadByte()
167 fallthrough // binary exponent not permitted
169 r.UnreadByte() // ch does not belong to exponent anymore
175 ch, err = r.ReadByte()
176 if err == nil && (ch == '+' || ch == '-') {
178 digits = append(digits, '-')
180 ch, err = r.ReadByte()
183 // prev encodes the previously seen char: it is one
184 // of '_', '0' (a digit), or '.' (anything else). A
185 // valid separator '_' may only occur after a digit.
192 if '0' <= ch && ch <= '9' {
193 digits = append(digits, ch)
196 } else if ch == '_' && sepOk {
202 r.UnreadByte() // ch does not belong to number anymore
205 ch, err = r.ReadByte()
211 if err == nil && !hasDigits {
215 exp, err = strconv.ParseInt(string(digits), 10, 64)
217 // other errors take precedence over invalid separators
218 if err == nil && (invalSep || prev == '_') {
225 // String returns a string representation of x in the form "a/b" (even if b == 1).
226 func (x *Rat) String() string {
227 return string(x.marshal())
230 // marshal implements String returning a slice of bytes
231 func (x *Rat) marshal() []byte {
233 buf = x.a.Append(buf, 10)
234 buf = append(buf, '/')
235 if len(x.b.abs) != 0 {
236 buf = x.b.Append(buf, 10)
238 buf = append(buf, '1')
243 // RatString returns a string representation of x in the form "a/b" if b != 1,
244 // and in the form "a" if b == 1.
245 func (x *Rat) RatString() string {
252 // FloatString returns a string representation of x in decimal form with prec
253 // digits of precision after the decimal point. The last digit is rounded to
254 // nearest, with halves rounded away from zero.
255 func (x *Rat) FloatString(prec int) string {
259 buf = x.a.Append(buf, 10)
261 buf = append(buf, '.')
262 for i := prec; i > 0; i-- {
263 buf = append(buf, '0')
270 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
274 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
278 r, r2 := r.div(nat(nil), r, x.b.abs)
280 // see if we need to round up
282 if x.b.abs.cmp(r2) <= 0 {
285 q = nat(nil).add(q, natOne)
286 r = nat(nil).sub(r, p)
291 buf = append(buf, '-')
293 buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
296 buf = append(buf, '.')
298 for i := prec - len(rs); i > 0; i-- {
299 buf = append(buf, '0')
301 buf = append(buf, rs...)