Source file
src/math/big/ratconv.go
1
2
3
4
5
6
7 package big
8
9 import (
10 "errors"
11 "fmt"
12 "io"
13 "strconv"
14 "strings"
15 )
16
17 func ratTok(ch rune) bool {
18 return strings.ContainsRune("+-/0123456789.eE", ch)
19 }
20
21 var ratZero Rat
22 var _ fmt.Scanner = &ratZero
23
24
25
26 func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
27 tok, err := s.Token(true, ratTok)
28 if err != nil {
29 return err
30 }
31 if !strings.ContainsRune("efgEFGv", ch) {
32 return errors.New("Rat.Scan: invalid verb")
33 }
34 if _, ok := z.SetString(string(tok)); !ok {
35 return errors.New("Rat.Scan: invalid syntax")
36 }
37 return nil
38 }
39
40
41
42
43
44
45 func (z *Rat) SetString(s string) (*Rat, bool) {
46 if len(s) == 0 {
47 return nil, false
48 }
49
50
51
52 if sep := strings.Index(s, "/"); sep >= 0 {
53 if _, ok := z.a.SetString(s[:sep], 0); !ok {
54 return nil, false
55 }
56 r := strings.NewReader(s[sep+1:])
57 var err error
58 if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
59 return nil, false
60 }
61
62 if _, err = r.ReadByte(); err != io.EOF {
63 return nil, false
64 }
65 if len(z.b.abs) == 0 {
66 return nil, false
67 }
68 return z.norm(), true
69 }
70
71
72 r := strings.NewReader(s)
73
74
75 neg, err := scanSign(r)
76 if err != nil {
77 return nil, false
78 }
79
80
81 var ecorr int
82 z.a.abs, _, ecorr, err = z.a.abs.scan(r, 10, true)
83 if err != nil {
84 return nil, false
85 }
86
87
88 var exp int64
89 exp, _, err = scanExponent(r, false)
90 if err != nil {
91 return nil, false
92 }
93
94
95 if _, err = r.ReadByte(); err != io.EOF {
96 return nil, false
97 }
98
99
100 if len(z.a.abs) == 0 {
101 return z, true
102 }
103
104
105
106 if ecorr < 0 {
107 exp += int64(ecorr)
108 }
109
110
111 expabs := exp
112 if expabs < 0 {
113 expabs = -expabs
114 }
115 powTen := nat(nil).expNN(natTen, nat(nil).setWord(Word(expabs)), nil)
116
117
118 if exp < 0 {
119 z.b.abs = powTen
120 z.norm()
121 } else {
122 z.a.abs = z.a.abs.mul(z.a.abs, powTen)
123 z.b.abs = z.b.abs[:0]
124 }
125
126 z.a.neg = neg && len(z.a.abs) > 0
127
128 return z, true
129 }
130
131
132
133
134
135
136
137
138
139
140
141 func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err error) {
142 base = 10
143
144 var ch byte
145 if ch, err = r.ReadByte(); err != nil {
146 if err == io.EOF {
147 err = nil
148 }
149 return
150 }
151
152 switch ch {
153 case 'e', 'E':
154
155 case 'p':
156 if binExpOk {
157 base = 2
158 break
159 }
160 fallthrough
161 default:
162 r.UnreadByte()
163 return
164 }
165
166 var neg bool
167 if neg, err = scanSign(r); err != nil {
168 return
169 }
170
171 var digits []byte
172 if neg {
173 digits = append(digits, '-')
174 }
175
176
177
178
179 for i := 0; ; i++ {
180 if ch, err = r.ReadByte(); err != nil {
181 if err != io.EOF || i == 0 {
182 return
183 }
184 err = nil
185 break
186 }
187 if ch < '0' || '9' < ch {
188 if i == 0 {
189 r.UnreadByte()
190 err = fmt.Errorf("invalid exponent (missing digits)")
191 return
192 }
193 break
194 }
195 digits = append(digits, ch)
196 }
197
198
199 exp, err = strconv.ParseInt(string(digits), 10, 64)
200 return
201 }
202
203
204 func (x *Rat) String() string {
205 return string(x.marshal())
206 }
207
208
209 func (x *Rat) marshal() []byte {
210 var buf []byte
211 buf = x.a.Append(buf, 10)
212 buf = append(buf, '/')
213 if len(x.b.abs) != 0 {
214 buf = x.b.Append(buf, 10)
215 } else {
216 buf = append(buf, '1')
217 }
218 return buf
219 }
220
221
222
223 func (x *Rat) RatString() string {
224 if x.IsInt() {
225 return x.a.String()
226 }
227 return x.String()
228 }
229
230
231
232
233 func (x *Rat) FloatString(prec int) string {
234 var buf []byte
235
236 if x.IsInt() {
237 buf = x.a.Append(buf, 10)
238 if prec > 0 {
239 buf = append(buf, '.')
240 for i := prec; i > 0; i-- {
241 buf = append(buf, '0')
242 }
243 }
244 return string(buf)
245 }
246
247
248 q, r := nat(nil).div(nat(nil), x.a.abs, x.b.abs)
249
250 p := natOne
251 if prec > 0 {
252 p = nat(nil).expNN(natTen, nat(nil).setUint64(uint64(prec)), nil)
253 }
254
255 r = r.mul(r, p)
256 r, r2 := r.div(nat(nil), r, x.b.abs)
257
258
259 r2 = r2.add(r2, r2)
260 if x.b.abs.cmp(r2) <= 0 {
261 r = r.add(r, natOne)
262 if r.cmp(p) >= 0 {
263 q = nat(nil).add(q, natOne)
264 r = nat(nil).sub(r, p)
265 }
266 }
267
268 if x.a.neg {
269 buf = append(buf, '-')
270 }
271 buf = append(buf, q.utoa(10)...)
272
273 if prec > 0 {
274 buf = append(buf, '.')
275 rs := r.utoa(10)
276 for i := prec - len(rs); i > 0; i-- {
277 buf = append(buf, '0')
278 }
279 buf = append(buf, rs...)
280 }
281
282 return string(buf)
283 }
284
View as plain text