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