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 (possibly signed) fraction "a/b", or as a
42 // floating-point number optionally followed by an exponent.
43 // If a fraction is provided, both the dividend and the divisor may be a
44 // decimal integer or independently use a prefix of ``0b'', ``0'' or ``0o'',
45 // or ``0x'' (or their upper-case variants) to denote a binary, octal, or
46 // hexadecimal integer, respectively. The divisor may not be signed.
47 // If a floating-point number is provided, it may be in decimal form or
48 // use any of the same prefixes as above but for ``0'' to denote a non-decimal
49 // mantissa. A leading ``0'' is considered a decimal leading 0; it does not
50 // indicate octal representation in this case.
51 // An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
52 // exponent may be provided as well, except for hexadecimal floats which
53 // only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
54 // be distinguished from a mantissa digit).
55 // The entire string, not just a prefix, must be valid for success. If the
56 // operation failed, the value of z is undefined but the returned value is nil.
57 func (z *Rat) SetString(s string) (*Rat, bool) {
63 // parse fraction a/b, if any
64 if sep := strings.Index(s, "/"); sep >= 0 {
65 if _, ok := z.a.SetString(s[:sep], 0); !ok {
68 r := strings.NewReader(s[sep+1:])
70 if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
73 // entire string must have been consumed
74 if _, err = r.ReadByte(); err != io.EOF {
77 if len(z.b.abs) == 0 {
83 // parse floating-point number
84 r := strings.NewReader(s)
87 neg, err := scanSign(r)
94 var fcount int // fractional digit count; valid if <= 0
95 z.a.abs, base, fcount, err = z.a.abs.scan(r, 0, true)
103 exp, ebase, err = scanExponent(r, true, true)
108 // there should be no unread characters left
109 if _, err = r.ReadByte(); err != io.EOF {
113 // special-case 0 (see also issue #16176)
114 if len(z.a.abs) == 0 {
119 // The mantissa may have a radix point (fcount <= 0) and there
120 // may be a nonzero exponent exp. The radix point amounts to a
121 // division by base**(-fcount), which equals a multiplication by
122 // base**fcount. An exponent means multiplication by ebase**exp.
123 // Multiplications are commutative, so we can apply them in any
124 // order. We only have powers of 2 and 10, and we split powers
125 // of 10 into the product of the same powers of 2 and 5. This
126 // may reduce the the size of shift/multiplication factors or
127 // divisors required to create the final fraction, depending
128 // on the actual floating-point value.
130 // determine binary or decimal exponent contribution of radix point
133 // The mantissa has a radix point ddd.dddd; and
134 // -fcount is the number of digits to the right
135 // of '.'. Adjust relevant exponent accordingly.
140 fallthrough // 10**e == 5**e * 2**e
144 exp2 = d * 3 // octal digits are 3 bits each
146 exp2 = d * 4 // hexadecimal digits are 4 bits each
148 panic("unexpected mantissa base")
150 // fcount consumed - not needed anymore
153 // take actual exponent into account
157 fallthrough // see fallthrough above
161 panic("unexpected exponent base")
163 // exp consumed - not needed anymore
165 // compute pow5 if needed
172 pow5 = pow5.expNN(natFive, nat(nil).setWord(Word(n)), nil)
175 // apply dividend contributions of exponents
176 // (start with exp5 so the numbers to multiply are smaller)
178 z.a.abs = z.a.abs.mul(z.a.abs, pow5)
182 if int64(uint(exp2)) != exp2 {
183 panic("exponent too large")
185 z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
189 // apply divisor contributions of exponents
190 z.b.abs = z.b.abs.setWord(1)
195 if int64(uint(-exp2)) != -exp2 {
196 panic("exponent too large")
198 z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
201 z.a.neg = neg && len(z.a.abs) > 0 // 0 has no sign
203 return z.norm(), true
206 // scanExponent scans the longest possible prefix of r representing a base 10
207 // (``e'', ``E'') or a base 2 (``p'', ``P'') exponent, if any. It returns the
208 // exponent, the exponent base (10 or 2), or a read or syntax error, if any.
210 // If sepOk is set, an underscore character ``_'' may appear between successive
211 // exponent digits; such underscores do not change the value of the exponent.
212 // Incorrect placement of underscores is reported as an error if there are no
213 // other errors. If sepOk is not set, underscores are not recognized and thus
214 // terminate scanning like any other character that is not a valid digit.
216 // exponent = ( "e" | "E" | "p" | "P" ) [ sign ] digits .
217 // sign = "+" | "-" .
218 // digits = digit { [ '_' ] digit } .
219 // digit = "0" ... "9" .
221 // A base 2 exponent is only permitted if base2ok is set.
222 func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, err error) {
223 // one char look-ahead
224 ch, err := r.ReadByte()
241 fallthrough // binary exponent not permitted
243 r.UnreadByte() // ch does not belong to exponent anymore
249 ch, err = r.ReadByte()
250 if err == nil && (ch == '+' || ch == '-') {
252 digits = append(digits, '-')
254 ch, err = r.ReadByte()
257 // prev encodes the previously seen char: it is one
258 // of '_', '0' (a digit), or '.' (anything else). A
259 // valid separator '_' may only occur after a digit.
266 if '0' <= ch && ch <= '9' {
267 digits = append(digits, ch)
270 } else if ch == '_' && sepOk {
276 r.UnreadByte() // ch does not belong to number anymore
279 ch, err = r.ReadByte()
285 if err == nil && !hasDigits {
289 exp, err = strconv.ParseInt(string(digits), 10, 64)
291 // other errors take precedence over invalid separators
292 if err == nil && (invalSep || prev == '_') {
299 // String returns a string representation of x in the form "a/b" (even if b == 1).
300 func (x *Rat) String() string {
301 return string(x.marshal())
304 // marshal implements String returning a slice of bytes
305 func (x *Rat) marshal() []byte {
307 buf = x.a.Append(buf, 10)
308 buf = append(buf, '/')
309 if len(x.b.abs) != 0 {
310 buf = x.b.Append(buf, 10)
312 buf = append(buf, '1')
317 // RatString returns a string representation of x in the form "a/b" if b != 1,
318 // and in the form "a" if b == 1.
319 func (x *Rat) RatString() string {
326 // FloatString returns a string representation of x in decimal form with prec
327 // digits of precision after the radix point. The last digit is rounded to
328 // nearest, with halves rounded away from zero.
329 func (x *Rat) FloatString(prec int) string {
333 buf = x.a.Append(buf, 10)
335 buf = append(buf, '.')
336 for i := prec; i > 0; i-- {
337 buf = append(buf, '0')
344 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
348 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
352 r, r2 := r.div(nat(nil), r, x.b.abs)
354 // see if we need to round up
356 if x.b.abs.cmp(r2) <= 0 {
359 q = nat(nil).add(q, natOne)
360 r = nat(nil).sub(r, p)
365 buf = append(buf, '-')
367 buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
370 buf = append(buf, '.')
372 for i := prec - len(rs); i > 0; i-- {
373 buf = append(buf, '0')
375 buf = append(buf, rs...)