Source file
src/math/big/ratconv_test.go
1
2
3
4
5 package big
6
7 import (
8 "bytes"
9 "fmt"
10 "io"
11 "math"
12 "reflect"
13 "strconv"
14 "strings"
15 "testing"
16 )
17
18 var exponentTests = []struct {
19 s string
20 base2ok bool
21 sepOk bool
22 x int64
23 b int
24 err error
25 next rune
26 }{
27
28 {"", false, false, 0, 10, nil, 0},
29 {"1", false, false, 0, 10, nil, '1'},
30 {"e0", false, false, 0, 10, nil, 0},
31 {"E1", false, false, 1, 10, nil, 0},
32 {"e+10", false, false, 10, 10, nil, 0},
33 {"e-10", false, false, -10, 10, nil, 0},
34 {"e123456789a", false, false, 123456789, 10, nil, 'a'},
35 {"p", false, false, 0, 10, nil, 'p'},
36 {"P+100", false, false, 0, 10, nil, 'P'},
37 {"p0", true, false, 0, 2, nil, 0},
38 {"P-123", true, false, -123, 2, nil, 0},
39 {"p+0a", true, false, 0, 2, nil, 'a'},
40 {"p+123__", true, false, 123, 2, nil, '_'},
41
42
43 {"e+1_0", false, true, 10, 10, nil, 0},
44 {"e-1_0", false, true, -10, 10, nil, 0},
45 {"e123_456_789a", false, true, 123456789, 10, nil, 'a'},
46 {"P+1_00", false, true, 0, 10, nil, 'P'},
47 {"p-1_2_3", true, true, -123, 2, nil, 0},
48
49
50 {"e", false, false, 0, 10, errNoDigits, 0},
51 {"ef", false, false, 0, 10, errNoDigits, 'f'},
52 {"e+", false, false, 0, 10, errNoDigits, 0},
53 {"E-x", false, false, 0, 10, errNoDigits, 'x'},
54 {"p", true, false, 0, 2, errNoDigits, 0},
55 {"P-", true, false, 0, 2, errNoDigits, 0},
56 {"p+e", true, false, 0, 2, errNoDigits, 'e'},
57 {"e+_x", false, true, 0, 10, errNoDigits, 'x'},
58
59
60 {"e0_", false, true, 0, 10, errInvalSep, 0},
61 {"e_0", false, true, 0, 10, errInvalSep, 0},
62 {"e-1_2__3", false, true, -123, 10, errInvalSep, 0},
63 }
64
65 func TestScanExponent(t *testing.T) {
66 for _, a := range exponentTests {
67 r := strings.NewReader(a.s)
68 x, b, err := scanExponent(r, a.base2ok, a.sepOk)
69 if err != a.err {
70 t.Errorf("scanExponent%+v\n\tgot error = %v; want %v", a, err, a.err)
71 }
72 if x != a.x {
73 t.Errorf("scanExponent%+v\n\tgot z = %v; want %v", a, x, a.x)
74 }
75 if b != a.b {
76 t.Errorf("scanExponent%+v\n\tgot b = %d; want %d", a, b, a.b)
77 }
78 next, _, err := r.ReadRune()
79 if err == io.EOF {
80 next = 0
81 err = nil
82 }
83 if err == nil && next != a.next {
84 t.Errorf("scanExponent%+v\n\tgot next = %q; want %q", a, next, a.next)
85 }
86 }
87 }
88
89 type StringTest struct {
90 in, out string
91 ok bool
92 }
93
94 var setStringTests = []StringTest{
95
96 {in: "1e"},
97 {in: "1.e"},
98 {in: "1e+14e-5"},
99 {in: "1e4.5"},
100 {in: "r"},
101 {in: "a/b"},
102 {in: "a.b"},
103 {in: "1/0"},
104 {in: "4/3/2"},
105 {in: "4/3/"},
106 {in: "4/3."},
107 {in: "4/"},
108 {in: "13e-9223372036854775808"},
109
110
111 {"0", "0", true},
112 {"-0", "0", true},
113 {"1", "1", true},
114 {"-1", "-1", true},
115 {"1.", "1", true},
116 {"1e0", "1", true},
117 {"1.e1", "10", true},
118 {"-0.1", "-1/10", true},
119 {"-.1", "-1/10", true},
120 {"2/4", "1/2", true},
121 {".25", "1/4", true},
122 {"-1/5", "-1/5", true},
123 {"8129567.7690E14", "812956776900000000000", true},
124 {"78189e+4", "781890000", true},
125 {"553019.8935e+8", "55301989350000", true},
126 {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
127 {"9877861857500000E-7", "3951144743/4", true},
128 {"2169378.417e-3", "2169378417/1000000", true},
129 {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
130 {"53/70893980658822810696", "53/70893980658822810696", true},
131 {"106/141787961317645621392", "53/70893980658822810696", true},
132 {"204211327800791583.81095", "4084226556015831676219/20000", true},
133 {"0e9999999999", "0", true},
134 }
135
136
137 var setStringTests2 = []StringTest{
138
139 {in: "4/3x"},
140 {in: "0/-1"},
141 {in: "-1/-1"},
142
143
144
145 {in: "10_/1"},
146 {in: "_10/1"},
147 {in: "1/1__0"},
148
149
150 {"0b1000/3", "8/3", true},
151 {"0B1000/0x8", "1", true},
152 {"-010/1", "-8", true},
153 {"-010.0", "-10", true},
154 {"-0o10/1", "-8", true},
155 {"0x10/1", "16", true},
156 {"0x10/0x20", "1/2", true},
157
158 {"0010", "10", true},
159 {"0x10.0", "16", true},
160 {"0x1.8", "3/2", true},
161 {"0X1.8p4", "24", true},
162 {"0x1.1E2", "2289/2048", true},
163 {"0b1.1E2", "150", true},
164 {"0B1.1P3", "12", true},
165 {"0o10e-2", "2/25", true},
166 {"0O10p-3", "1", true},
167
168
169
170 {"0b_1000/3", "8/3", true},
171 {"0B_10_00/0x8", "1", true},
172 {"0xdead/0B1101_1110_1010_1101", "1", true},
173 {"0B1101_1110_1010_1101/0XD_E_A_D", "1", true},
174 {"1_000.0", "1000", true},
175
176 {"0x_10.0", "16", true},
177 {"0x1_0.0", "16", true},
178 {"0x1.8_0", "3/2", true},
179 {"0X1.8p0_4", "24", true},
180 {"0b1.1_0E2", "150", true},
181 {"0o1_0e-2", "2/25", true},
182 {"0O_10p-3", "1", true},
183 }
184
185 func TestRatSetString(t *testing.T) {
186 var tests []StringTest
187 tests = append(tests, setStringTests...)
188 tests = append(tests, setStringTests2...)
189
190 for i, test := range tests {
191 x, ok := new(Rat).SetString(test.in)
192
193 if ok {
194 if !test.ok {
195 t.Errorf("#%d SetString(%q) expected failure", i, test.in)
196 } else if x.RatString() != test.out {
197 t.Errorf("#%d SetString(%q) got %s want %s", i, test.in, x.RatString(), test.out)
198 }
199 } else {
200 if test.ok {
201 t.Errorf("#%d SetString(%q) expected success", i, test.in)
202 } else if x != nil {
203 t.Errorf("#%d SetString(%q) got %p want nil", i, test.in, x)
204 }
205 }
206 }
207 }
208
209 func TestRatSetStringZero(t *testing.T) {
210 got, _ := new(Rat).SetString("0")
211 want := new(Rat).SetInt64(0)
212 if !reflect.DeepEqual(got, want) {
213 t.Errorf("got %#+v, want %#+v", got, want)
214 }
215 }
216
217 func TestRatScan(t *testing.T) {
218 var buf bytes.Buffer
219 for i, test := range setStringTests {
220 x := new(Rat)
221 buf.Reset()
222 buf.WriteString(test.in)
223
224 _, err := fmt.Fscanf(&buf, "%v", x)
225 if err == nil != test.ok {
226 if test.ok {
227 t.Errorf("#%d (%s) error: %s", i, test.in, err)
228 } else {
229 t.Errorf("#%d (%s) expected error", i, test.in)
230 }
231 continue
232 }
233 if err == nil && x.RatString() != test.out {
234 t.Errorf("#%d got %s want %s", i, x.RatString(), test.out)
235 }
236 }
237 }
238
239 var floatStringTests = []struct {
240 in string
241 prec int
242 out string
243 }{
244 {"0", 0, "0"},
245 {"0", 4, "0.0000"},
246 {"1", 0, "1"},
247 {"1", 2, "1.00"},
248 {"-1", 0, "-1"},
249 {"0.05", 1, "0.1"},
250 {"-0.05", 1, "-0.1"},
251 {".25", 2, "0.25"},
252 {".25", 1, "0.3"},
253 {".25", 3, "0.250"},
254 {"-1/3", 3, "-0.333"},
255 {"-2/3", 4, "-0.6667"},
256 {"0.96", 1, "1.0"},
257 {"0.999", 2, "1.00"},
258 {"0.9", 0, "1"},
259 {".25", -1, "0"},
260 {".55", -1, "1"},
261 }
262
263 func TestFloatString(t *testing.T) {
264 for i, test := range floatStringTests {
265 x, _ := new(Rat).SetString(test.in)
266
267 if x.FloatString(test.prec) != test.out {
268 t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
269 }
270 }
271 }
272
273
274
275 var float64inputs = []string{
276
277
278
279 "5e+125",
280 "69e+267",
281 "999e-026",
282 "7861e-034",
283 "75569e-254",
284 "928609e-261",
285 "9210917e+080",
286 "84863171e+114",
287 "653777767e+273",
288 "5232604057e-298",
289 "27235667517e-109",
290 "653532977297e-123",
291 "3142213164987e-294",
292 "46202199371337e-072",
293 "231010996856685e-073",
294 "9324754620109615e+212",
295 "78459735791271921e+049",
296 "272104041512242479e+200",
297 "6802601037806061975e+198",
298 "20505426358836677347e-221",
299 "836168422905420598437e-234",
300 "4891559871276714924261e+222",
301
302
303 "9e-265",
304 "85e-037",
305 "623e+100",
306 "3571e+263",
307 "81661e+153",
308 "920657e-023",
309 "4603285e-024",
310 "87575437e-309",
311 "245540327e+122",
312 "6138508175e+120",
313 "83356057653e+193",
314 "619534293513e+124",
315 "2335141086879e+218",
316 "36167929443327e-159",
317 "609610927149051e-255",
318 "3743626360493413e-165",
319 "94080055902682397e-242",
320 "899810892172646163e+283",
321 "7120190517612959703e+120",
322 "25188282901709339043e-252",
323 "308984926168550152811e-052",
324 "6372891218502368041059e+064",
325
326
327 "5e-20",
328 "67e+14",
329 "985e+15",
330 "7693e-42",
331 "55895e-16",
332 "996622e-44",
333 "7038531e-32",
334 "60419369e-46",
335 "702990899e-20",
336 "6930161142e-48",
337 "25933168707e+13",
338 "596428896559e+20",
339
340
341 "3e-23",
342 "57e+18",
343 "789e-35",
344 "2539e-18",
345 "76173e+28",
346 "887745e-11",
347 "5382571e-37",
348 "82381273e-35",
349 "750486563e-38",
350 "3752432815e-39",
351 "75224575729e-45",
352 "459926601011e+15",
353
354
355
356 "0",
357 "1",
358 "+1",
359 "1e23",
360 "1E23",
361 "100000000000000000000000",
362 "1e-100",
363 "123456700",
364 "99999999999999974834176",
365 "100000000000000000000001",
366 "100000000000000008388608",
367 "100000000000000016777215",
368 "100000000000000016777216",
369 "-1",
370 "-0.1",
371 "-0",
372 "1e-20",
373 "625e-3",
374
375
376 "1.7976931348623157e308",
377 "-1.7976931348623157e308",
378
379 "1.7976931348623159e308",
380 "-1.7976931348623159e308",
381
382
383 "1.7976931348623158e308",
384 "-1.7976931348623158e308",
385
386 "1.797693134862315808e308",
387 "-1.797693134862315808e308",
388
389
390 "1e308",
391 "2e308",
392 "1e309",
393
394
395 "1e310",
396 "-1e310",
397 "1e400",
398 "-1e400",
399 "long:1e400000",
400 "long:-1e400000",
401
402
403 "1e-305",
404 "1e-306",
405 "1e-307",
406 "1e-308",
407 "1e-309",
408 "1e-310",
409 "1e-322",
410
411 "5e-324",
412 "4e-324",
413 "3e-324",
414
415 "2e-324",
416
417 "1e-350",
418 "long:1e-400000",
419
420 "-1e-350",
421 "long:-1e-400000",
422
423
424
425
426
427
428
429
430
431 "2.2250738585072012e-308",
432
433 "2.2250738585072011e-308",
434
435
436 "4.630813248087435e+307",
437
438
439 "22.222222222222222",
440 "long:2." + strings.Repeat("2", 4000) + "e+1",
441
442
443
444 "1.00000000000000011102230246251565404236316680908203125",
445
446 "1.00000000000000011102230246251565404236316680908203124",
447
448 "1.00000000000000011102230246251565404236316680908203126",
449
450 "long:1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1",
451
452
453 "4.940656458412465441765687928682213723651e-324",
454
455 "2.470328229206232720882843964341106861825e-324",
456
457
458 "2.470328302827751011111470718709768633275e-324",
459
460
461 "2.225073858507201136057409796709131975935e-308",
462
463 "1152921504606846975",
464 "-1152921504606846975",
465 "1152921504606846977",
466 "-1152921504606846977",
467
468 "1/3",
469 }
470
471
472
473 func isFinite(f float64) bool {
474 return math.Abs(f) <= math.MaxFloat64
475 }
476
477 func TestFloat32SpecialCases(t *testing.T) {
478 for _, input := range float64inputs {
479 if strings.HasPrefix(input, "long:") {
480 if !*long {
481 continue
482 }
483 input = input[len("long:"):]
484 }
485
486 r, ok := new(Rat).SetString(input)
487 if !ok {
488 t.Errorf("Rat.SetString(%q) failed", input)
489 continue
490 }
491 f, exact := r.Float32()
492
493
494
495
496 if !strings.Contains(input, "/") {
497 e64, _ := strconv.ParseFloat(input, 32)
498 e := float32(e64)
499
500
501
502
503 switch {
504 case math.Float32bits(e) == math.Float32bits(f):
505
506 case f == 0 && r.Num().BitLen() == 0:
507
508 default:
509 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
510 }
511 }
512
513 if !isFinite(float64(f)) {
514 continue
515 }
516
517
518 if !checkIsBestApprox32(t, f, r) {
519
520 t.Errorf("(input was %q)", input)
521 }
522
523
524 checkNonLossyRoundtrip32(t, f)
525
526
527 if wasExact := new(Rat).SetFloat64(float64(f)).Cmp(r) == 0; wasExact != exact {
528 t.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input, exact, wasExact)
529 }
530 }
531 }
532
533 func TestFloat64SpecialCases(t *testing.T) {
534 for _, input := range float64inputs {
535 if strings.HasPrefix(input, "long:") {
536 if !*long {
537 continue
538 }
539 input = input[len("long:"):]
540 }
541
542 r, ok := new(Rat).SetString(input)
543 if !ok {
544 t.Errorf("Rat.SetString(%q) failed", input)
545 continue
546 }
547 f, exact := r.Float64()
548
549
550
551
552 if !strings.Contains(input, "/") {
553 e, _ := strconv.ParseFloat(input, 64)
554
555
556
557
558 switch {
559 case math.Float64bits(e) == math.Float64bits(f):
560
561 case f == 0 && r.Num().BitLen() == 0:
562
563 default:
564 t.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input, e, e, f, f, f-e)
565 }
566 }
567
568 if !isFinite(f) {
569 continue
570 }
571
572
573 if !checkIsBestApprox64(t, f, r) {
574
575 t.Errorf("(input was %q)", input)
576 }
577
578
579 checkNonLossyRoundtrip64(t, f)
580
581
582 if wasExact := new(Rat).SetFloat64(f).Cmp(r) == 0; wasExact != exact {
583 t.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input, exact, wasExact)
584 }
585 }
586 }
587
588 func TestIssue31184(t *testing.T) {
589 var x Rat
590 for _, want := range []string{
591 "-213.090",
592 "8.192",
593 "16.000",
594 } {
595 x.SetString(want)
596 got := x.FloatString(3)
597 if got != want {
598 t.Errorf("got %s, want %s", got, want)
599 }
600 }
601 }
602
603 func TestIssue45910(t *testing.T) {
604 var x Rat
605 for _, test := range []struct {
606 input string
607 want bool
608 }{
609 {"1e-1000001", false},
610 {"1e-1000000", true},
611 {"1e+1000000", true},
612 {"1e+1000001", false},
613
614 {"0p1000000000000", true},
615 {"1p-10000001", false},
616 {"1p-10000000", true},
617 {"1p+10000000", true},
618 {"1p+10000001", false},
619 {"1.770p02041010010011001001", false},
620 } {
621 _, got := x.SetString(test.input)
622 if got != test.want {
623 t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)
624 }
625 }
626 }
627 func TestFloatPrec(t *testing.T) {
628 var tests = []struct {
629 f string
630 prec int
631 ok bool
632 fdec string
633 }{
634
635 {"10/100", 1, true, "0.1"},
636 {"3/100", 2, true, "0.03"},
637 {"10", 0, true, "10"},
638
639
640 {"zero", 0, true, "0"},
641 {"0", 0, true, "0"},
642 {"1", 0, true, "1"},
643 {"1/2", 1, true, "0.5"},
644 {"1/3", 0, false, "0"},
645 {"1/4", 2, true, "0.25"},
646 {"1/5", 1, true, "0.2"},
647 {"1/6", 1, false, "0.2"},
648 {"1/7", 0, false, "0"},
649 {"1/8", 3, true, "0.125"},
650 {"1/9", 0, false, "0"},
651 {"1/10", 1, true, "0.1"},
652 {"1/11", 0, false, "0"},
653 {"1/12", 2, false, "0.08"},
654 {"1/13", 0, false, "0"},
655 {"1/14", 1, false, "0.1"},
656 {"1/15", 1, false, "0.1"},
657 {"1/16", 4, true, "0.0625"},
658
659 {"10/2", 0, true, "5"},
660 {"10/3", 0, false, "3"},
661 {"10/6", 0, false, "2"},
662 {"1/10000000", 7, true, "0.0000001"},
663 {"1/3125", 5, true, "0.00032"},
664 {"1/1024", 10, true, "0.0009765625"},
665 {"1/304000", 7, false, "0.0000033"},
666 {"1/48828125", 11, true, "0.00000002048"},
667 }
668
669 for _, test := range tests {
670 var f Rat
671
672
673 if test.f != "zero" {
674 _, ok := f.SetString(test.f)
675 if !ok {
676 t.Fatalf("invalid test case: f = %s", test.f)
677 }
678 }
679
680
681 fdec := test.fdec
682 for i := 0; i < 2; i++ {
683 prec, ok := f.FloatPrec()
684 if prec != test.prec || ok != test.ok {
685 t.Errorf("%s: FloatPrec(%s): got prec, ok = %d, %v; want %d, %v", test.f, &f, prec, ok, test.prec, test.ok)
686 }
687 s := f.FloatString(test.prec)
688 if s != fdec {
689 t.Errorf("%s: FloatString(%s, %d): got %s; want %s", test.f, &f, prec, s, fdec)
690 }
691
692 if f.Sign() > 0 {
693 f.Neg(&f)
694 fdec = "-" + fdec
695 }
696 }
697 }
698 }
699
700 func BenchmarkFloatPrecExact(b *testing.B) {
701 for _, n := range []int{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6} {
702
703 d := NewInt(5)
704 p := NewInt(int64(n))
705 d.Exp(d, p, nil)
706
707
708 var r Rat
709 r.SetFrac(NewInt(1), d)
710
711 b.Run(fmt.Sprint(n), func(b *testing.B) {
712 for i := 0; i < b.N; i++ {
713 prec, ok := r.FloatPrec()
714 if prec != n || !ok {
715 b.Fatalf("got exact, ok = %d, %v; want %d, %v", prec, ok, uint64(n), true)
716 }
717 }
718 })
719 }
720 }
721
722 func BenchmarkFloatPrecMixed(b *testing.B) {
723 for _, n := range []int{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6} {
724
725 d := NewInt(3 * 5 * 7 * 11)
726 p := NewInt(int64(n))
727 d.Exp(d, p, nil)
728
729
730 var r Rat
731 r.SetFrac(NewInt(1), d)
732
733 b.Run(fmt.Sprint(n), func(b *testing.B) {
734 for i := 0; i < b.N; i++ {
735 prec, ok := r.FloatPrec()
736 if prec != n || ok {
737 b.Fatalf("got exact, ok = %d, %v; want %d, %v", prec, ok, uint64(n), false)
738 }
739 }
740 })
741 }
742 }
743
744 func BenchmarkFloatPrecInexact(b *testing.B) {
745 for _, n := range []int{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6} {
746
747 d := NewInt(5)
748 p := NewInt(int64(n))
749 d.Exp(d, p, nil)
750 d.Add(d, NewInt(1))
751
752
753 var r Rat
754 r.SetFrac(NewInt(1), d)
755
756 b.Run(fmt.Sprint(n), func(b *testing.B) {
757 for i := 0; i < b.N; i++ {
758 _, ok := r.FloatPrec()
759 if ok {
760 b.Fatalf("got unexpected ok")
761 }
762 }
763 })
764 }
765 }
766
View as plain text