# Source file src/math/big/floatconv_test.go

```     1  // Copyright 2015 The Go Authors. All rights reserved.
2  // Use of this source code is governed by a BSD-style
4
5  package big
6
7  import (
8  	"bytes"
9  	"fmt"
10  	"math"
11  	"math/bits"
12  	"strconv"
13  	"testing"
14  )
15
16  var zero_ float64
17
18  func TestFloatSetFloat64String(t *testing.T) {
19  	inf := math.Inf(0)
20  	nan := math.NaN()
21
22  	for _, test := range []struct {
23  		s string
24  		x float64 // NaNs represent invalid inputs
25  	}{
26  		// basics
27  		{"0", 0},
28  		{"-0", -zero_},
29  		{"+0", 0},
30  		{"1", 1},
31  		{"-1", -1},
32  		{"+1", 1},
33  		{"1.234", 1.234},
34  		{"-1.234", -1.234},
35  		{"+1.234", 1.234},
36  		{".1", 0.1},
37  		{"1.", 1},
38  		{"+1.", 1},
39
40  		// various zeros
41  		{"0e100", 0},
42  		{"-0e+100", -zero_},
43  		{"+0e-100", 0},
44  		{"0E100", 0},
45  		{"-0E+100", -zero_},
46  		{"+0E-100", 0},
47
48  		// various decimal exponent formats
49  		{"1.e10", 1e10},
50  		{"1e+10", 1e10},
51  		{"+1e-10", 1e-10},
52  		{"1E10", 1e10},
53  		{"1.E+10", 1e10},
54  		{"+1E-10", 1e-10},
55
56  		// infinities
57  		{"Inf", inf},
58  		{"+Inf", inf},
59  		{"-Inf", -inf},
60  		{"inf", inf},
61  		{"+inf", inf},
62  		{"-inf", -inf},
63
64  		// invalid numbers
65  		{"", nan},
66  		{"-", nan},
67  		{"0x", nan},
68  		{"0e", nan},
69  		{"1.2ef", nan},
70  		{"2..3", nan},
71  		{"123..", nan},
72  		{"infinity", nan},
73  		{"foobar", nan},
74
75  		// invalid underscores
76  		{"_", nan},
77  		{"0_", nan},
78  		{"1__0", nan},
79  		{"123_.", nan},
80  		{"123._", nan},
81  		{"123._4", nan},
82  		{"1_2.3_4_", nan},
83  		{"_.123", nan},
84  		{"_123.456", nan},
85  		{"10._0", nan},
86  		{"10.0e_0", nan},
87  		{"10.0e0_", nan},
88  		{"0P-0__0", nan},
89
90  		// misc decimal values
91  		{"3.14159265", 3.14159265},
92  		{"-687436.79457e-245", -687436.79457e-245},
93  		{"-687436.79457E245", -687436.79457e245},
94  		{".0000000000000000000000000000000000000001", 1e-40},
95  		{"+10000000000000000000000000000000000000000e-0", 1e40},
96
97  		// decimal mantissa, binary exponent
98  		{"0p0", 0},
99  		{"-0p0", -zero_},
100  		{"1p10", 1 << 10},
101  		{"1p+10", 1 << 10},
102  		{"+1p-10", 1.0 / (1 << 10)},
103  		{"1024p-12", 0.25},
104  		{"-1p10", -1024},
105  		{"1.5p1", 3},
106
107  		// binary mantissa, decimal exponent
108  		{"0b0", 0},
109  		{"-0b0", -zero_},
110  		{"0b0e+10", 0},
111  		{"-0b0e-10", -zero_},
112  		{"0b1010", 10},
113  		{"0B1010E2", 1000},
114  		{"0b.1", 0.5},
115  		{"0b.001", 0.125},
116  		{"0b.001e3", 125},
117
118  		// binary mantissa, binary exponent
119  		{"0b0p+10", 0},
120  		{"-0b0p-10", -zero_},
121  		{"0b.1010p4", 10},
122  		{"0b1p-1", 0.5},
123  		{"0b001p-3", 0.125},
124  		{"0b.001p3", 1},
125  		{"0b0.01p2", 1},
126  		{"0b0.01P+2", 1},
127
128  		// octal mantissa, decimal exponent
129  		{"0o0", 0},
130  		{"-0o0", -zero_},
131  		{"0o0e+10", 0},
132  		{"-0o0e-10", -zero_},
133  		{"0o12", 10},
134  		{"0O12E2", 1000},
135  		{"0o.4", 0.5},
136  		{"0o.01", 0.015625},
137  		{"0o.01e3", 15.625},
138
139  		// octal mantissa, binary exponent
140  		{"0o0p+10", 0},
141  		{"-0o0p-10", -zero_},
142  		{"0o.12p6", 10},
143  		{"0o4p-3", 0.5},
144  		{"0o0014p-6", 0.1875},
145  		{"0o.001p9", 1},
146  		{"0o0.01p7", 2},
147  		{"0O0.01P+2", 0.0625},
148
149  		// hexadecimal mantissa and exponent
150  		{"0x0", 0},
151  		{"-0x0", -zero_},
152  		{"0x0p+10", 0},
153  		{"-0x0p-10", -zero_},
154  		{"0xff", 255},
155  		{"0X.8p1", 1},
156  		{"-0X0.00008p16", -0.5},
157  		{"-0X0.00008P+16", -0.5},
158  		{"0x0.0000000000001p-1022", math.SmallestNonzeroFloat64},
159  		{"0x1.fffffffffffffp1023", math.MaxFloat64},
160
161  		// underscores
162  		{"0_0", 0},
163  		{"1_000.", 1000},
164  		{"1_2_3.4_5_6", 123.456},
165  		{"1.0e0_0", 1},
166  		{"1p+1_0", 1024},
167  		{"0b_1000", 0x8},
168  		{"0b_1011_1101", 0xbd},
169  		{"0x_f0_0d_1eP+0_8", 0xf00d1e00},
170  	} {
171  		var x Float
172  		x.SetPrec(53)
173  		_, ok := x.SetString(test.s)
174  		if math.IsNaN(test.x) {
175  			// test.s is invalid
176  			if ok {
177  				t.Errorf("%s: want parse error", test.s)
178  			}
179  			continue
180  		}
181  		// test.s is valid
182  		if !ok {
183  			t.Errorf("%s: got parse error", test.s)
184  			continue
185  		}
186  		f, _ := x.Float64()
187  		want := new(Float).SetFloat64(test.x)
188  		if x.Cmp(want) != 0 || x.Signbit() != want.Signbit() {
189  			t.Errorf("%s: got %v (%v); want %v", test.s, &x, f, test.x)
190  		}
191  	}
192  }
193
194  func fdiv(a, b float64) float64 { return a / b }
195
196  const (
197  	below1e23 = 99999999999999974834176
198  	above1e23 = 100000000000000008388608
199  )
200
201  func TestFloat64Text(t *testing.T) {
202  	for _, test := range []struct {
203  		x      float64
204  		format byte
205  		prec   int
206  		want   string
207  	}{
208  		{0, 'f', 0, "0"},
209  		{math.Copysign(0, -1), 'f', 0, "-0"},
210  		{1, 'f', 0, "1"},
211  		{-1, 'f', 0, "-1"},
212
213  		{0.001, 'e', 0, "1e-03"},
214  		{0.459, 'e', 0, "5e-01"},
215  		{1.459, 'e', 0, "1e+00"},
216  		{2.459, 'e', 1, "2.5e+00"},
217  		{3.459, 'e', 2, "3.46e+00"},
218  		{4.459, 'e', 3, "4.459e+00"},
219  		{5.459, 'e', 4, "5.4590e+00"},
220
221  		{0.001, 'f', 0, "0"},
222  		{0.459, 'f', 0, "0"},
223  		{1.459, 'f', 0, "1"},
224  		{2.459, 'f', 1, "2.5"},
225  		{3.459, 'f', 2, "3.46"},
226  		{4.459, 'f', 3, "4.459"},
227  		{5.459, 'f', 4, "5.4590"},
228
229  		{0, 'b', 0, "0"},
230  		{math.Copysign(0, -1), 'b', 0, "-0"},
231  		{1.0, 'b', 0, "4503599627370496p-52"},
232  		{-1.0, 'b', 0, "-4503599627370496p-52"},
233  		{4503599627370496, 'b', 0, "4503599627370496p+0"},
234
235  		{0, 'p', 0, "0"},
236  		{math.Copysign(0, -1), 'p', 0, "-0"},
237  		{1024.0, 'p', 0, "0x.8p+11"},
238  		{-1024.0, 'p', 0, "-0x.8p+11"},
239
240  		// all test cases below from strconv/ftoa_test.go
241  		{1, 'e', 5, "1.00000e+00"},
242  		{1, 'f', 5, "1.00000"},
243  		{1, 'g', 5, "1"},
244  		{1, 'g', -1, "1"},
245  		{20, 'g', -1, "20"},
246  		{1234567.8, 'g', -1, "1.2345678e+06"},
247  		{200000, 'g', -1, "200000"},
248  		{2000000, 'g', -1, "2e+06"},
249
250  		// g conversion and zero suppression
251  		{400, 'g', 2, "4e+02"},
252  		{40, 'g', 2, "40"},
253  		{4, 'g', 2, "4"},
254  		{.4, 'g', 2, "0.4"},
255  		{.04, 'g', 2, "0.04"},
256  		{.004, 'g', 2, "0.004"},
257  		{.0004, 'g', 2, "0.0004"},
258  		{.00004, 'g', 2, "4e-05"},
259  		{.000004, 'g', 2, "4e-06"},
260
261  		{0, 'e', 5, "0.00000e+00"},
262  		{0, 'f', 5, "0.00000"},
263  		{0, 'g', 5, "0"},
264  		{0, 'g', -1, "0"},
265
266  		{-1, 'e', 5, "-1.00000e+00"},
267  		{-1, 'f', 5, "-1.00000"},
268  		{-1, 'g', 5, "-1"},
269  		{-1, 'g', -1, "-1"},
270
271  		{12, 'e', 5, "1.20000e+01"},
272  		{12, 'f', 5, "12.00000"},
273  		{12, 'g', 5, "12"},
274  		{12, 'g', -1, "12"},
275
276  		{123456700, 'e', 5, "1.23457e+08"},
277  		{123456700, 'f', 5, "123456700.00000"},
278  		{123456700, 'g', 5, "1.2346e+08"},
279  		{123456700, 'g', -1, "1.234567e+08"},
280
281  		{1.2345e6, 'e', 5, "1.23450e+06"},
282  		{1.2345e6, 'f', 5, "1234500.00000"},
283  		{1.2345e6, 'g', 5, "1.2345e+06"},
284
285  		{1e23, 'e', 17, "9.99999999999999916e+22"},
286  		{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
287  		{1e23, 'g', 17, "9.9999999999999992e+22"},
288
289  		{1e23, 'e', -1, "1e+23"},
290  		{1e23, 'f', -1, "100000000000000000000000"},
291  		{1e23, 'g', -1, "1e+23"},
292
293  		{below1e23, 'e', 17, "9.99999999999999748e+22"},
294  		{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
295  		{below1e23, 'g', 17, "9.9999999999999975e+22"},
296
297  		{below1e23, 'e', -1, "9.999999999999997e+22"},
298  		{below1e23, 'f', -1, "99999999999999970000000"},
299  		{below1e23, 'g', -1, "9.999999999999997e+22"},
300
301  		{above1e23, 'e', 17, "1.00000000000000008e+23"},
302  		{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
303  		{above1e23, 'g', 17, "1.0000000000000001e+23"},
304
305  		{above1e23, 'e', -1, "1.0000000000000001e+23"},
306  		{above1e23, 'f', -1, "100000000000000010000000"},
307  		{above1e23, 'g', -1, "1.0000000000000001e+23"},
308
309  		{5e-304 / 1e20, 'g', -1, "5e-324"},
310  		{-5e-304 / 1e20, 'g', -1, "-5e-324"},
311  		{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},   // avoid constant arithmetic
312  		{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
313
314  		{32, 'g', -1, "32"},
315  		{32, 'g', 0, "3e+01"},
316
317  		{100, 'x', -1, "0x1.9p+06"},
318
319  		// {math.NaN(), 'g', -1, "NaN"},  // Float doesn't support NaNs
320  		// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
321  		{math.Inf(0), 'g', -1, "+Inf"},
322  		{math.Inf(-1), 'g', -1, "-Inf"},
323  		{-math.Inf(0), 'g', -1, "-Inf"},
324
325  		{-1, 'b', -1, "-4503599627370496p-52"},
326
327  		// fixed bugs
328  		{0.9, 'f', 1, "0.9"},
329  		{0.09, 'f', 1, "0.1"},
330  		{0.0999, 'f', 1, "0.1"},
331  		{0.05, 'f', 1, "0.1"},
332  		{0.05, 'f', 0, "0"},
333  		{0.5, 'f', 1, "0.5"},
334  		{0.5, 'f', 0, "0"},
335  		{1.5, 'f', 0, "2"},
336
337  		// https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
338  		{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
339  		// https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
340  		{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
341
342  		// Issue 2625.
343  		{383260575764816448, 'f', 0, "383260575764816448"},
344  		{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
345
346  		// Issue 15918.
347  		{1, 'f', -10, "1"},
348  		{1, 'f', -11, "1"},
349  		{1, 'f', -12, "1"},
350  	} {
351  		// The test cases are from the strconv package which tests float64 values.
352  		// When formatting values with prec = -1 (shortest representation),
353  		// the actually available mantissa precision matters.
354  		// For denormalized values, that precision is < 53 (SetFloat64 default).
355  		// Compute and set the actual precision explicitly.
356  		f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x)
357  		got := f.Text(test.format, test.prec)
358  		if got != test.want {
359  			t.Errorf("%v: got %s; want %s", test, got, test.want)
360  			continue
361  		}
362
363  		if test.format == 'b' && test.x == 0 {
364  			continue // 'b' format in strconv.Float requires knowledge of bias for 0.0
365  		}
366  		if test.format == 'p' {
367  			continue // 'p' format not supported in strconv.Format
368  		}
369
370  		// verify that Float format matches strconv format
371  		want := strconv.FormatFloat(test.x, test.format, test.prec, 64)
372  		if got != want {
373  			t.Errorf("%v: got %s; want %s (strconv)", test, got, want)
374  		}
375  	}
376  }
377
378  // actualPrec returns the number of actually used mantissa bits.
379  func actualPrec(x float64) uint {
380  	if mant := math.Float64bits(x); x != 0 && mant&(0x7ff<<52) == 0 {
381  		// x is denormalized
383  	}
384  	return 53
385  }
386
387  func TestFloatText(t *testing.T) {
388  	const defaultRound = ^RoundingMode(0)
389
390  	for _, test := range []struct {
391  		x      string
392  		round  RoundingMode
393  		prec   uint
394  		format byte
395  		digits int
396  		want   string
397  	}{
398  		{"0", defaultRound, 10, 'f', 0, "0"},
399  		{"-0", defaultRound, 10, 'f', 0, "-0"},
400  		{"1", defaultRound, 10, 'f', 0, "1"},
401  		{"-1", defaultRound, 10, 'f', 0, "-1"},
402
403  		{"1.459", defaultRound, 100, 'e', 0, "1e+00"},
404  		{"2.459", defaultRound, 100, 'e', 1, "2.5e+00"},
405  		{"3.459", defaultRound, 100, 'e', 2, "3.46e+00"},
406  		{"4.459", defaultRound, 100, 'e', 3, "4.459e+00"},
407  		{"5.459", defaultRound, 100, 'e', 4, "5.4590e+00"},
408
409  		{"1.459", defaultRound, 100, 'E', 0, "1E+00"},
410  		{"2.459", defaultRound, 100, 'E', 1, "2.5E+00"},
411  		{"3.459", defaultRound, 100, 'E', 2, "3.46E+00"},
412  		{"4.459", defaultRound, 100, 'E', 3, "4.459E+00"},
413  		{"5.459", defaultRound, 100, 'E', 4, "5.4590E+00"},
414
415  		{"1.459", defaultRound, 100, 'f', 0, "1"},
416  		{"2.459", defaultRound, 100, 'f', 1, "2.5"},
417  		{"3.459", defaultRound, 100, 'f', 2, "3.46"},
418  		{"4.459", defaultRound, 100, 'f', 3, "4.459"},
419  		{"5.459", defaultRound, 100, 'f', 4, "5.4590"},
420
421  		{"1.459", defaultRound, 100, 'g', 0, "1"},
422  		{"2.459", defaultRound, 100, 'g', 1, "2"},
423  		{"3.459", defaultRound, 100, 'g', 2, "3.5"},
424  		{"4.459", defaultRound, 100, 'g', 3, "4.46"},
425  		{"5.459", defaultRound, 100, 'g', 4, "5.459"},
426
427  		{"1459", defaultRound, 53, 'g', 0, "1e+03"},
428  		{"2459", defaultRound, 53, 'g', 1, "2e+03"},
429  		{"3459", defaultRound, 53, 'g', 2, "3.5e+03"},
430  		{"4459", defaultRound, 53, 'g', 3, "4.46e+03"},
431  		{"5459", defaultRound, 53, 'g', 4, "5459"},
432
433  		{"1459", defaultRound, 53, 'G', 0, "1E+03"},
434  		{"2459", defaultRound, 53, 'G', 1, "2E+03"},
435  		{"3459", defaultRound, 53, 'G', 2, "3.5E+03"},
436  		{"4459", defaultRound, 53, 'G', 3, "4.46E+03"},
437  		{"5459", defaultRound, 53, 'G', 4, "5459"},
438
439  		{"3", defaultRound, 10, 'e', 40, "3.0000000000000000000000000000000000000000e+00"},
440  		{"3", defaultRound, 10, 'f', 40, "3.0000000000000000000000000000000000000000"},
441  		{"3", defaultRound, 10, 'g', 40, "3"},
442
443  		{"3e40", defaultRound, 100, 'e', 40, "3.0000000000000000000000000000000000000000e+40"},
444  		{"3e40", defaultRound, 100, 'f', 4, "30000000000000000000000000000000000000000.0000"},
445  		{"3e40", defaultRound, 100, 'g', 40, "3e+40"},
446
447  		// make sure "stupid" exponents don't stall the machine
448  		{"1e1000000", defaultRound, 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
449  		{"1e646456992", defaultRound, 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
450  		{"1e646456993", defaultRound, 64, 'p', 0, "+Inf"},
451  		{"1e1000000000", defaultRound, 64, 'p', 0, "+Inf"},
452  		{"1e-1000000", defaultRound, 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
453  		{"1e-646456993", defaultRound, 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
454  		{"1e-646456994", defaultRound, 64, 'p', 0, "0"},
455  		{"1e-1000000000", defaultRound, 64, 'p', 0, "0"},
456
457  		// minimum and maximum values
458  		{"1p2147483646", defaultRound, 64, 'p', 0, "0x.8p+2147483647"},
459  		{"0x.8p2147483647", defaultRound, 64, 'p', 0, "0x.8p+2147483647"},
460  		{"0x.8p-2147483647", defaultRound, 64, 'p', 0, "0x.8p-2147483647"},
461  		{"1p-2147483649", defaultRound, 64, 'p', 0, "0x.8p-2147483648"},
462
463  		// TODO(gri) need tests for actual large Floats
464
465  		{"0", defaultRound, 53, 'b', 0, "0"},
466  		{"-0", defaultRound, 53, 'b', 0, "-0"},
467  		{"1.0", defaultRound, 53, 'b', 0, "4503599627370496p-52"},
468  		{"-1.0", defaultRound, 53, 'b', 0, "-4503599627370496p-52"},
469  		{"4503599627370496", defaultRound, 53, 'b', 0, "4503599627370496p+0"},
470
471  		// issue 9939
472  		{"3", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
473  		{"03", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
474  		{"3.", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
475  		{"3.0", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
476  		{"3.00", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
477  		{"3.000", defaultRound, 350, 'b', 0, "1720123961992553633708115671476565205597423741876210842803191629540192157066363606052513914832594264915968p-348"},
478
479  		{"3", defaultRound, 350, 'p', 0, "0x.cp+2"},
480  		{"03", defaultRound, 350, 'p', 0, "0x.cp+2"},
481  		{"3.", defaultRound, 350, 'p', 0, "0x.cp+2"},
482  		{"3.0", defaultRound, 350, 'p', 0, "0x.cp+2"},
483  		{"3.00", defaultRound, 350, 'p', 0, "0x.cp+2"},
484  		{"3.000", defaultRound, 350, 'p', 0, "0x.cp+2"},
485
486  		{"0", defaultRound, 64, 'p', 0, "0"},
487  		{"-0", defaultRound, 64, 'p', 0, "-0"},
488  		{"1024.0", defaultRound, 64, 'p', 0, "0x.8p+11"},
489  		{"-1024.0", defaultRound, 64, 'p', 0, "-0x.8p+11"},
490
491  		{"0", defaultRound, 64, 'x', -1, "0x0p+00"},
492  		{"0", defaultRound, 64, 'x', 0, "0x0p+00"},
493  		{"0", defaultRound, 64, 'x', 1, "0x0.0p+00"},
494  		{"0", defaultRound, 64, 'x', 5, "0x0.00000p+00"},
495  		{"3.25", defaultRound, 64, 'x', 0, "0x1p+02"},
496  		{"-3.25", defaultRound, 64, 'x', 0, "-0x1p+02"},
497  		{"3.25", defaultRound, 64, 'x', 1, "0x1.ap+01"},
498  		{"-3.25", defaultRound, 64, 'x', 1, "-0x1.ap+01"},
499  		{"3.25", defaultRound, 64, 'x', -1, "0x1.ap+01"},
500  		{"-3.25", defaultRound, 64, 'x', -1, "-0x1.ap+01"},
501  		{"1024.0", defaultRound, 64, 'x', 0, "0x1p+10"},
502  		{"-1024.0", defaultRound, 64, 'x', 0, "-0x1p+10"},
503  		{"1024.0", defaultRound, 64, 'x', 5, "0x1.00000p+10"},
504  		{"8191.0", defaultRound, 53, 'x', -1, "0x1.fffp+12"},
505  		{"8191.5", defaultRound, 53, 'x', -1, "0x1.fff8p+12"},
506  		{"8191.53125", defaultRound, 53, 'x', -1, "0x1.fff88p+12"},
507  		{"8191.53125", defaultRound, 53, 'x', 4, "0x1.fff8p+12"},
508  		{"8191.53125", defaultRound, 53, 'x', 3, "0x1.000p+13"},
509  		{"8191.53125", defaultRound, 53, 'x', 0, "0x1p+13"},
510  		{"8191.533203125", defaultRound, 53, 'x', -1, "0x1.fff888p+12"},
511  		{"8191.533203125", defaultRound, 53, 'x', 5, "0x1.fff88p+12"},
512  		{"8191.533203125", defaultRound, 53, 'x', 4, "0x1.fff9p+12"},
513
514  		{"8191.53125", defaultRound, 53, 'x', -1, "0x1.fff88p+12"},
515  		{"8191.53125", ToNearestEven, 53, 'x', 5, "0x1.fff88p+12"},
516  		{"8191.53125", ToNearestAway, 53, 'x', 5, "0x1.fff88p+12"},
517  		{"8191.53125", ToZero, 53, 'x', 5, "0x1.fff88p+12"},
518  		{"8191.53125", AwayFromZero, 53, 'x', 5, "0x1.fff88p+12"},
519  		{"8191.53125", ToNegativeInf, 53, 'x', 5, "0x1.fff88p+12"},
520  		{"8191.53125", ToPositiveInf, 53, 'x', 5, "0x1.fff88p+12"},
521
522  		{"8191.53125", defaultRound, 53, 'x', 4, "0x1.fff8p+12"},
523  		{"8191.53125", defaultRound, 53, 'x', 3, "0x1.000p+13"},
524  		{"8191.53125", defaultRound, 53, 'x', 0, "0x1p+13"},
525  		{"8191.533203125", defaultRound, 53, 'x', -1, "0x1.fff888p+12"},
526  		{"8191.533203125", defaultRound, 53, 'x', 6, "0x1.fff888p+12"},
527  		{"8191.533203125", defaultRound, 53, 'x', 5, "0x1.fff88p+12"},
528  		{"8191.533203125", defaultRound, 53, 'x', 4, "0x1.fff9p+12"},
529
530  		{"8191.53125", ToNearestEven, 53, 'x', 4, "0x1.fff8p+12"},
531  		{"8191.53125", ToNearestAway, 53, 'x', 4, "0x1.fff9p+12"},
532  		{"8191.53125", ToZero, 53, 'x', 4, "0x1.fff8p+12"},
533  		{"8191.53125", ToZero, 53, 'x', 2, "0x1.ffp+12"},
534  		{"8191.53125", AwayFromZero, 53, 'x', 4, "0x1.fff9p+12"},
535  		{"8191.53125", ToNegativeInf, 53, 'x', 4, "0x1.fff8p+12"},
536  		{"-8191.53125", ToNegativeInf, 53, 'x', 4, "-0x1.fff9p+12"},
537  		{"8191.53125", ToPositiveInf, 53, 'x', 4, "0x1.fff9p+12"},
538  		{"-8191.53125", ToPositiveInf, 53, 'x', 4, "-0x1.fff8p+12"},
539
540  		// issue 34343
541  		{"0x.8p-2147483648", ToNearestEven, 4, 'p', -1, "0x.8p-2147483648"},
542  		{"0x.8p-2147483648", ToNearestEven, 4, 'x', -1, "0x1p-2147483649"},
543  	} {
544  		f, _, err := ParseFloat(test.x, 0, test.prec, ToNearestEven)
545  		if err != nil {
546  			t.Errorf("%v: %s", test, err)
547  			continue
548  		}
549  		if test.round != defaultRound {
550  			f.SetMode(test.round)
551  		}
552
553  		got := f.Text(test.format, test.digits)
554  		if got != test.want {
555  			t.Errorf("%v: got %s; want %s", test, got, test.want)
556  		}
557
558  		// compare with strconv.FormatFloat output if possible
559  		// ('p' format is not supported by strconv.FormatFloat,
560  		// and its output for 0.0 prints a biased exponent value
561  		// as in 0p-1074 which makes no sense to emulate here)
562  		if test.prec == 53 && test.format != 'p' && f.Sign() != 0 && (test.round == ToNearestEven || test.round == defaultRound) {
563  			f64, acc := f.Float64()
564  			if acc != Exact {
565  				t.Errorf("%v: expected exact conversion to float64", test)
566  				continue
567  			}
568  			got := strconv.FormatFloat(f64, test.format, test.digits, 64)
569  			if got != test.want {
570  				t.Errorf("%v: got %s; want %s", test, got, test.want)
571  			}
572  		}
573  	}
574  }
575
576  func TestFloatFormat(t *testing.T) {
577  	for _, test := range []struct {
578  		format string
579  		value  any // float32, float64, or string (== 512bit *Float)
580  		want   string
581  	}{
582  		// from fmt/fmt_test.go
583  		{"%+.3e", 0.0, "+0.000e+00"},
584  		{"%+.3e", 1.0, "+1.000e+00"},
585  		{"%+.3f", -1.0, "-1.000"},
586  		{"%+.3F", -1.0, "-1.000"},
587  		{"%+.3F", float32(-1.0), "-1.000"},
588  		{"%+07.2f", 1.0, "+001.00"},
589  		{"%+07.2f", -1.0, "-001.00"},
590  		{"%+10.2f", +1.0, "     +1.00"},
591  		{"%+10.2f", -1.0, "     -1.00"},
592  		{"% .3E", -1.0, "-1.000E+00"},
593  		{"% .3e", 1.0, " 1.000e+00"},
594  		{"%+.3g", 0.0, "+0"},
595  		{"%+.3g", 1.0, "+1"},
596  		{"%+.3g", -1.0, "-1"},
597  		{"% .3g", -1.0, "-1"},
598  		{"% .3g", 1.0, " 1"},
599  		{"%b", float32(1.0), "8388608p-23"},
600  		{"%b", 1.0, "4503599627370496p-52"},
601
602  		// from fmt/fmt_test.go: old test/fmt_test.go
603  		{"%e", 1.0, "1.000000e+00"},
604  		{"%e", 1234.5678e3, "1.234568e+06"},
605  		{"%e", 1234.5678e-8, "1.234568e-05"},
606  		{"%e", -7.0, "-7.000000e+00"},
607  		{"%e", -1e-9, "-1.000000e-09"},
608  		{"%f", 1234.5678e3, "1234567.800000"},
609  		{"%f", 1234.5678e-8, "0.000012"},
610  		{"%f", -7.0, "-7.000000"},
611  		{"%f", -1e-9, "-0.000000"},
612  		{"%g", 1234.5678e3, "1.2345678e+06"},
613  		{"%g", float32(1234.5678e3), "1.2345678e+06"},
614  		{"%g", 1234.5678e-8, "1.2345678e-05"},
615  		{"%g", -7.0, "-7"},
616  		{"%g", -1e-9, "-1e-09"},
617  		{"%g", float32(-1e-9), "-1e-09"},
618  		{"%E", 1.0, "1.000000E+00"},
619  		{"%E", 1234.5678e3, "1.234568E+06"},
620  		{"%E", 1234.5678e-8, "1.234568E-05"},
621  		{"%E", -7.0, "-7.000000E+00"},
622  		{"%E", -1e-9, "-1.000000E-09"},
623  		{"%G", 1234.5678e3, "1.2345678E+06"},
624  		{"%G", float32(1234.5678e3), "1.2345678E+06"},
625  		{"%G", 1234.5678e-8, "1.2345678E-05"},
626  		{"%G", -7.0, "-7"},
627  		{"%G", -1e-9, "-1E-09"},
628  		{"%G", float32(-1e-9), "-1E-09"},
629
630  		{"%20.6e", 1.2345e3, "        1.234500e+03"},
631  		{"%20.6e", 1.2345e-3, "        1.234500e-03"},
632  		{"%20e", 1.2345e3, "        1.234500e+03"},
633  		{"%20e", 1.2345e-3, "        1.234500e-03"},
634  		{"%20.8e", 1.2345e3, "      1.23450000e+03"},
635  		{"%20f", 1.23456789e3, "         1234.567890"},
636  		{"%20f", 1.23456789e-3, "            0.001235"},
637  		{"%20f", 12345678901.23456789, "  12345678901.234568"},
638  		{"%-20f", 1.23456789e3, "1234.567890         "},
639  		{"%20.8f", 1.23456789e3, "       1234.56789000"},
640  		{"%20.8f", 1.23456789e-3, "          0.00123457"},
641  		{"%g", 1.23456789e3, "1234.56789"},
642  		{"%g", 1.23456789e-3, "0.00123456789"},
643  		{"%g", 1.23456789e20, "1.23456789e+20"},
644  		{"%20e", math.Inf(1), "                +Inf"},
645  		{"%-20f", math.Inf(-1), "-Inf                "},
646
647  		// from fmt/fmt_test.go: comparison of padding rules with C printf
648  		{"%.2f", 1.0, "1.00"},
649  		{"%.2f", -1.0, "-1.00"},
650  		{"% .2f", 1.0, " 1.00"},
651  		{"% .2f", -1.0, "-1.00"},
652  		{"%+.2f", 1.0, "+1.00"},
653  		{"%+.2f", -1.0, "-1.00"},
654  		{"%7.2f", 1.0, "   1.00"},
655  		{"%7.2f", -1.0, "  -1.00"},
656  		{"% 7.2f", 1.0, "   1.00"},
657  		{"% 7.2f", -1.0, "  -1.00"},
658  		{"%+7.2f", 1.0, "  +1.00"},
659  		{"%+7.2f", -1.0, "  -1.00"},
660  		{"%07.2f", 1.0, "0001.00"},
661  		{"%07.2f", -1.0, "-001.00"},
662  		{"% 07.2f", 1.0, " 001.00"},
663  		{"% 07.2f", -1.0, "-001.00"},
664  		{"%+07.2f", 1.0, "+001.00"},
665  		{"%+07.2f", -1.0, "-001.00"},
666
667  		// from fmt/fmt_test.go: zero padding does not apply to infinities
668  		{"%020f", math.Inf(-1), "                -Inf"},
669  		{"%020f", math.Inf(+1), "                +Inf"},
670  		{"% 020f", math.Inf(-1), "                -Inf"},
671  		{"% 020f", math.Inf(+1), "                 Inf"},
672  		{"%+020f", math.Inf(-1), "                -Inf"},
673  		{"%+020f", math.Inf(+1), "                +Inf"},
674  		{"%20f", -1.0, "           -1.000000"},
675
676  		// handle %v like %g
677  		{"%v", 0.0, "0"},
678  		{"%v", -7.0, "-7"},
679  		{"%v", -1e-9, "-1e-09"},
680  		{"%v", float32(-1e-9), "-1e-09"},
681  		{"%010v", 0.0, "0000000000"},
682
683  		// *Float cases
684  		{"%.20f", "1e-20", "0.00000000000000000001"},
685  		{"%.20f", "-1e-20", "-0.00000000000000000001"},
686  		{"%30.20f", "-1e-20", "       -0.00000000000000000001"},
687  		{"%030.20f", "-1e-20", "-00000000.00000000000000000001"},
688  		{"%030.20f", "+1e-20", "000000000.00000000000000000001"},
689  		{"% 030.20f", "+1e-20", " 00000000.00000000000000000001"},
690
691  		// erroneous formats
692  		{"%s", 1.0, "%!s(*big.Float=1)"},
693  	} {
694  		value := new(Float)
695  		switch v := test.value.(type) {
696  		case float32:
697  			value.SetPrec(24).SetFloat64(float64(v))
698  		case float64:
699  			value.SetPrec(53).SetFloat64(v)
700  		case string:
701  			value.SetPrec(512).Parse(v, 0)
702  		default:
703  			t.Fatalf("unsupported test value: %v (%T)", v, v)
704  		}
705
706  		if got := fmt.Sprintf(test.format, value); got != test.want {
707  			t.Errorf("%v: got %q; want %q", test, got, test.want)
708  		}
709  	}
710  }
711
712  func BenchmarkParseFloatSmallExp(b *testing.B) {
713  	for i := 0; i < b.N; i++ {
714  		for _, s := range []string{
715  			"1e0",
716  			"1e-1",
717  			"1e-2",
718  			"1e-3",
719  			"1e-4",
720  			"1e-5",
721  			"1e-10",
722  			"1e-20",
723  			"1e-50",
724  			"1e1",
725  			"1e2",
726  			"1e3",
727  			"1e4",
728  			"1e5",
729  			"1e10",
730  			"1e20",
731  			"1e50",
732  		} {
733  			var x Float
734  			_, _, err := x.Parse(s, 0)
735  			if err != nil {
736  				b.Fatalf("%s: %v", s, err)
737  			}
738  		}
739  	}
740  }
741
742  func BenchmarkParseFloatLargeExp(b *testing.B) {
743  	for i := 0; i < b.N; i++ {
744  		for _, s := range []string{
745  			"1e0",
746  			"1e-10",
747  			"1e-20",
748  			"1e-30",
749  			"1e-40",
750  			"1e-50",
751  			"1e-100",
752  			"1e-500",
753  			"1e-1000",
754  			"1e-5000",
755  			"1e-10000",
756  			"1e10",
757  			"1e20",
758  			"1e30",
759  			"1e40",
760  			"1e50",
761  			"1e100",
762  			"1e500",
763  			"1e1000",
764  			"1e5000",
765  			"1e10000",
766  		} {
767  			var x Float
768  			_, _, err := x.Parse(s, 0)
769  			if err != nil {
770  				b.Fatalf("%s: %v", s, err)
771  			}
772  		}
773  	}
774  }
775
776  func TestFloatScan(t *testing.T) {
777  	var floatScanTests = []struct {
778  		input     string
779  		format    string
780  		output    string
781  		remaining int
782  		wantErr   bool
783  	}{
784  		0: {"10.0", "%f", "10", 0, false},
785  		1: {"23.98+2.0", "%v", "23.98", 4, false},
786  		2: {"-1+1", "%v", "-1", 2, false},
787  		3: {" 00000", "%v", "0", 0, false},
788  		4: {"-123456p-78", "%b", "-4.084816388e-19", 0, false},
789  		5: {"+123", "%b", "123", 0, false},
790  		6: {"-1.234e+56", "%e", "-1.234e+56", 0, false},
791  		7: {"-1.234E-56", "%E", "-1.234e-56", 0, false},
792  		8: {"-1.234e+567", "%g", "-1.234e+567", 0, false},
793  		9: {"+1234567891011.234", "%G", "1.234567891e+12", 0, false},
794
795  		// Scan doesn't handle ±Inf.
796  		10: {"Inf", "%v", "", 3, true},
797  		11: {"-Inf", "%v", "", 3, true},
798  		12: {"-Inf", "%v", "", 3, true},
799  	}
800
801  	var buf bytes.Buffer
802  	for i, test := range floatScanTests {
803  		x := new(Float)
804  		buf.Reset()
805  		buf.WriteString(test.input)
806  		_, err := fmt.Fscanf(&buf, test.format, x)
807  		if test.wantErr {
808  			if err == nil {
809  				t.Errorf("#%d want non-nil err", i)
810  			}
811  			continue
812  		}
813
814  		if err != nil {
815  			t.Errorf("#%d error: %s", i, err)
816  		}
817
818  		if x.String() != test.output {
819  			t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
820  		}
821  		if buf.Len() != test.remaining {
822  			t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
823  		}
824  	}
825  }
826
```

View as plain text