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