Source file
src/math/big/ftoa.go
1
2
3
4
5
6
7
8
9 package big
10
11 import (
12 "bytes"
13 "fmt"
14 "strconv"
15 )
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 func (x *Float) Text(format byte, prec int) string {
44 cap := 10
45 if prec > 0 {
46 cap += prec
47 }
48 return string(x.Append(make([]byte, 0, cap), format, prec))
49 }
50
51
52
53 func (x *Float) String() string {
54 return x.Text('g', 10)
55 }
56
57
58
59 func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
60
61 if x.neg {
62 buf = append(buf, '-')
63 }
64
65
66 if x.form == inf {
67 if !x.neg {
68 buf = append(buf, '+')
69 }
70 return append(buf, "Inf"...)
71 }
72
73
74 switch fmt {
75 case 'b':
76 return x.fmtB(buf)
77 case 'p':
78 return x.fmtP(buf)
79 }
80
81
82
83
84
85
86
87 var d decimal
88 if x.form == finite {
89
90 d.init(x.mant, int(x.exp)-x.mant.bitLen())
91 }
92
93
94 shortest := false
95 if prec < 0 {
96 shortest = true
97 roundShortest(&d, x)
98
99 switch fmt {
100 case 'e', 'E':
101 prec = len(d.mant) - 1
102 case 'f':
103 prec = max(len(d.mant)-d.exp, 0)
104 case 'g', 'G':
105 prec = len(d.mant)
106 }
107 } else {
108
109 switch fmt {
110 case 'e', 'E':
111
112 d.round(1 + prec)
113 case 'f':
114
115 d.round(d.exp + prec)
116 case 'g', 'G':
117 if prec == 0 {
118 prec = 1
119 }
120 d.round(prec)
121 }
122 }
123
124
125 switch fmt {
126 case 'e', 'E':
127 return fmtE(buf, fmt, prec, d)
128 case 'f':
129 return fmtF(buf, prec, d)
130 case 'g', 'G':
131
132 eprec := prec
133 if eprec > len(d.mant) && len(d.mant) >= d.exp {
134 eprec = len(d.mant)
135 }
136
137
138
139
140 if shortest {
141 eprec = 6
142 }
143 exp := d.exp - 1
144 if exp < -4 || exp >= eprec {
145 if prec > len(d.mant) {
146 prec = len(d.mant)
147 }
148 return fmtE(buf, fmt+'e'-'g', prec-1, d)
149 }
150 if prec > d.exp {
151 prec = len(d.mant)
152 }
153 return fmtF(buf, max(prec-d.exp, 0), d)
154 }
155
156
157 if x.neg {
158 buf = buf[:len(buf)-1]
159 }
160 return append(buf, '%', fmt)
161 }
162
163 func roundShortest(d *decimal, x *Float) {
164
165 if len(d.mant) == 0 {
166 return
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180 mant := nat(nil).set(x.mant)
181 exp := int(x.exp) - mant.bitLen()
182 s := mant.bitLen() - int(x.prec+1)
183 switch {
184 case s < 0:
185 mant = mant.shl(mant, uint(-s))
186 case s > 0:
187 mant = mant.shr(mant, uint(+s))
188 }
189 exp += s
190
191
192
193 var lower decimal
194 var tmp nat
195 lower.init(tmp.sub(mant, natOne), exp)
196
197
198 var upper decimal
199 upper.init(tmp.add(mant, natOne), exp)
200
201
202
203
204 inclusive := mant[0]&2 == 0
205
206
207
208 for i, m := range d.mant {
209 l := lower.at(i)
210 u := upper.at(i)
211
212
213
214
215 okdown := l != m || inclusive && i+1 == len(lower.mant)
216
217
218
219 okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
220
221
222
223 switch {
224 case okdown && okup:
225 d.round(i + 1)
226 return
227 case okdown:
228 d.roundDown(i + 1)
229 return
230 case okup:
231 d.roundUp(i + 1)
232 return
233 }
234 }
235 }
236
237
238 func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
239
240 ch := byte('0')
241 if len(d.mant) > 0 {
242 ch = d.mant[0]
243 }
244 buf = append(buf, ch)
245
246
247 if prec > 0 {
248 buf = append(buf, '.')
249 i := 1
250 m := min(len(d.mant), prec+1)
251 if i < m {
252 buf = append(buf, d.mant[i:m]...)
253 i = m
254 }
255 for ; i <= prec; i++ {
256 buf = append(buf, '0')
257 }
258 }
259
260
261 buf = append(buf, fmt)
262 var exp int64
263 if len(d.mant) > 0 {
264 exp = int64(d.exp) - 1
265 }
266 if exp < 0 {
267 ch = '-'
268 exp = -exp
269 } else {
270 ch = '+'
271 }
272 buf = append(buf, ch)
273
274
275 if exp < 10 {
276 buf = append(buf, '0')
277 }
278 return strconv.AppendInt(buf, exp, 10)
279 }
280
281
282 func fmtF(buf []byte, prec int, d decimal) []byte {
283
284 if d.exp > 0 {
285 m := min(len(d.mant), d.exp)
286 buf = append(buf, d.mant[:m]...)
287 for ; m < d.exp; m++ {
288 buf = append(buf, '0')
289 }
290 } else {
291 buf = append(buf, '0')
292 }
293
294
295 if prec > 0 {
296 buf = append(buf, '.')
297 for i := 0; i < prec; i++ {
298 buf = append(buf, d.at(d.exp+i))
299 }
300 }
301
302 return buf
303 }
304
305
306
307
308
309
310
311 func (x *Float) fmtB(buf []byte) []byte {
312 if x.form == zero {
313 return append(buf, '0')
314 }
315
316 if debugFloat && x.form != finite {
317 panic("non-finite float")
318 }
319
320
321
322 m := x.mant
323 switch w := uint32(len(x.mant)) * _W; {
324 case w < x.prec:
325 m = nat(nil).shl(m, uint(x.prec-w))
326 case w > x.prec:
327 m = nat(nil).shr(m, uint(w-x.prec))
328 }
329
330 buf = append(buf, m.utoa(10)...)
331 buf = append(buf, 'p')
332 e := int64(x.exp) - int64(x.prec)
333 if e >= 0 {
334 buf = append(buf, '+')
335 }
336 return strconv.AppendInt(buf, e, 10)
337 }
338
339
340
341
342
343
344 func (x *Float) fmtP(buf []byte) []byte {
345 if x.form == zero {
346 return append(buf, '0')
347 }
348
349 if debugFloat && x.form != finite {
350 panic("non-finite float")
351 }
352
353
354
355
356 m := x.mant
357 i := 0
358 for i < len(m) && m[i] == 0 {
359 i++
360 }
361 m = m[i:]
362
363 buf = append(buf, "0x."...)
364 buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
365 buf = append(buf, 'p')
366 if x.exp >= 0 {
367 buf = append(buf, '+')
368 }
369 return strconv.AppendInt(buf, int64(x.exp), 10)
370 }
371
372 func min(x, y int) int {
373 if x < y {
374 return x
375 }
376 return y
377 }
378
379 var _ fmt.Formatter = &floatZero
380
381
382
383
384
385
386
387
388
389
390 func (x *Float) Format(s fmt.State, format rune) {
391 prec, hasPrec := s.Precision()
392 if !hasPrec {
393 prec = 6
394 }
395
396 switch format {
397 case 'e', 'E', 'f', 'b', 'p':
398
399 case 'F':
400
401 format = 'f'
402 case 'v':
403
404 format = 'g'
405 fallthrough
406 case 'g', 'G':
407 if !hasPrec {
408 prec = -1
409 }
410 default:
411 fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
412 return
413 }
414 var buf []byte
415 buf = x.Append(buf, byte(format), prec)
416 if len(buf) == 0 {
417 buf = []byte("?")
418 }
419
420
421 var sign string
422 switch {
423 case buf[0] == '-':
424 sign = "-"
425 buf = buf[1:]
426 case buf[0] == '+':
427
428 sign = "+"
429 if s.Flag(' ') {
430 sign = " "
431 }
432 buf = buf[1:]
433 case s.Flag('+'):
434 sign = "+"
435 case s.Flag(' '):
436 sign = " "
437 }
438
439 var padding int
440 if width, hasWidth := s.Width(); hasWidth && width > len(sign)+len(buf) {
441 padding = width - len(sign) - len(buf)
442 }
443
444 switch {
445 case s.Flag('0') && !x.IsInf():
446
447 writeMultiple(s, sign, 1)
448 writeMultiple(s, "0", padding)
449 s.Write(buf)
450 case s.Flag('-'):
451
452 writeMultiple(s, sign, 1)
453 s.Write(buf)
454 writeMultiple(s, " ", padding)
455 default:
456
457 writeMultiple(s, " ", padding)
458 writeMultiple(s, sign, 1)
459 s.Write(buf)
460 }
461 }
462
View as plain text