1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 var exponentTests
= []struct {
18 s
string // string to be scanned
19 base2ok
bool // true if 'p'/'P' exponents are accepted
20 sepOk
bool // true if '_' separators are accepted
21 x
int64 // expected exponent
22 b
int // expected exponent base
23 err error
// expected error
24 next rune
// next character (or 0, if at EOF)
26 // valid, without separators
27 {"", false, false, 0, 10, nil, 0},
28 {"1", false, false, 0, 10, nil, '1'},
29 {"e0", false, false, 0, 10, nil, 0},
30 {"E1", false, false, 1, 10, nil, 0},
31 {"e+10", false, false, 10, 10, nil, 0},
32 {"e-10", false, false, -10, 10, nil, 0},
33 {"e123456789a", false, false, 123456789, 10, nil, 'a'},
34 {"p", false, false, 0, 10, nil, 'p'},
35 {"P+100", false, false, 0, 10, nil, 'P'},
36 {"p0", true, false, 0, 2, nil, 0},
37 {"P-123", true, false, -123, 2, nil, 0},
38 {"p+0a", true, false, 0, 2, nil, 'a'},
39 {"p+123__", true, false, 123, 2, nil, '_'}, // '_' is not part of the number anymore
41 // valid, with separators
42 {"e+1_0", false, true, 10, 10, nil, 0},
43 {"e-1_0", false, true, -10, 10, nil, 0},
44 {"e123_456_789a", false, true, 123456789, 10, nil, 'a'},
45 {"P+1_00", false, true, 0, 10, nil, 'P'},
46 {"p-1_2_3", true, true, -123, 2, nil, 0},
49 {"e", false, false, 0, 10, errNoDigits
, 0},
50 {"ef", false, false, 0, 10, errNoDigits
, 'f'},
51 {"e+", false, false, 0, 10, errNoDigits
, 0},
52 {"E-x", false, false, 0, 10, errNoDigits
, 'x'},
53 {"p", true, false, 0, 2, errNoDigits
, 0},
54 {"P-", true, false, 0, 2, errNoDigits
, 0},
55 {"p+e", true, false, 0, 2, errNoDigits
, 'e'},
56 {"e+_x", false, true, 0, 10, errNoDigits
, 'x'},
58 // invalid: incorrect use of separator
59 {"e0_", false, true, 0, 10, errInvalSep
, 0},
60 {"e_0", false, true, 0, 10, errInvalSep
, 0},
61 {"e-1_2__3", false, true, -123, 10, errInvalSep
, 0},
64 func TestScanExponent(t
*testing
.T
) {
65 for _
, a
:= range exponentTests
{
66 r
:= strings
.NewReader(a
.s
)
67 x
, b
, err
:= scanExponent(r
, a
.base2ok
, a
.sepOk
)
69 t
.Errorf("scanExponent%+v\n\tgot error = %v; want %v", a
, err
, a
.err
)
72 t
.Errorf("scanExponent%+v\n\tgot z = %v; want %v", a
, x
, a
.x
)
75 t
.Errorf("scanExponent%+v\n\tgot b = %d; want %d", a
, b
, a
.b
)
77 next
, _
, err
:= r
.ReadRune()
82 if err
== nil && next
!= a
.next
{
83 t
.Errorf("scanExponent%+v\n\tgot next = %q; want %q", a
, next
, a
.next
)
88 type StringTest
struct {
93 var setStringTests
= []StringTest
{
103 {in
: "4/3/2"}, // issue 17001
115 {"1.e1", "10", true},
116 {"-0.1", "-1/10", true},
117 {"-.1", "-1/10", true},
118 {"2/4", "1/2", true},
119 {".25", "1/4", true},
120 {"-1/5", "-1/5", true},
121 {"8129567.7690E14", "812956776900000000000", true},
122 {"78189e+4", "781890000", true},
123 {"553019.8935e+8", "55301989350000", true},
124 {"98765432109876543210987654321e-10", "98765432109876543210987654321/10000000000", true},
125 {"9877861857500000E-7", "3951144743/4", true},
126 {"2169378.417e-3", "2169378417/1000000", true},
127 {"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
128 {"53/70893980658822810696", "53/70893980658822810696", true},
129 {"106/141787961317645621392", "53/70893980658822810696", true},
130 {"204211327800791583.81095", "4084226556015831676219/20000", true},
131 {"0e9999999999", "0", true}, // issue #16176
134 // These are not supported by fmt.Fscanf.
135 var setStringTests2
= []StringTest
{
141 // invalid with separators
142 // (smoke tests only - a comprehensive set of tests is in natconv_test.go)
148 {"0b1000/3", "8/3", true},
149 {"0B1000/0x8", "1", true},
150 {"-010/1", "-8", true}, // 0-prefix indicates octal in this case
151 {"-010.0", "-10", true},
152 {"-0o10/1", "-8", true},
153 {"0x10/1", "16", true},
154 {"0x10/0x20", "1/2", true},
156 {"0010", "10", true}, // 0-prefix is ignored in this case (not a fraction)
157 {"0x10.0", "16", true},
158 {"0x1.8", "3/2", true},
159 {"0X1.8p4", "24", true},
160 {"0x1.1E2", "2289/2048", true}, // E is part of hex mantissa, not exponent
161 {"0b1.1E2", "150", true},
162 {"0B1.1P3", "12", true},
163 {"0o10e-2", "2/25", true},
164 {"0O10p-3", "1", true},
166 // valid with separators
167 // (smoke tests only - a comprehensive set of tests is in natconv_test.go)
168 {"0b_1000/3", "8/3", true},
169 {"0B_10_00/0x8", "1", true},
170 {"0xdead/0B1101_1110_1010_1101", "1", true},
171 {"0B1101_1110_1010_1101/0XD_E_A_D", "1", true},
172 {"1_000.0", "1000", true},
174 {"0x_10.0", "16", true},
175 {"0x1_0.0", "16", true},
176 {"0x1.8_0", "3/2", true},
177 {"0X1.8p0_4", "24", true},
178 {"0b1.1_0E2", "150", true},
179 {"0o1_0e-2", "2/25", true},
180 {"0O_10p-3", "1", true},
183 func TestRatSetString(t
*testing
.T
) {
184 var tests
[]StringTest
185 tests
= append(tests
, setStringTests
...)
186 tests
= append(tests
, setStringTests2
...)
188 for i
, test
:= range tests
{
189 x
, ok
:= new(Rat
).SetString(test
.in
)
193 t
.Errorf("#%d SetString(%q) expected failure", i
, test
.in
)
194 } else if x
.RatString() != test
.out
{
195 t
.Errorf("#%d SetString(%q) got %s want %s", i
, test
.in
, x
.RatString(), test
.out
)
199 t
.Errorf("#%d SetString(%q) expected success", i
, test
.in
)
201 t
.Errorf("#%d SetString(%q) got %p want nil", i
, test
.in
, x
)
207 func TestRatScan(t
*testing
.T
) {
209 for i
, test
:= range setStringTests
{
212 buf
.WriteString(test
.in
)
214 _
, err
:= fmt
.Fscanf(&buf
, "%v", x
)
215 if err
== nil != test
.ok
{
217 t
.Errorf("#%d (%s) error: %s", i
, test
.in
, err
)
219 t
.Errorf("#%d (%s) expected error", i
, test
.in
)
223 if err
== nil && x
.RatString() != test
.out
{
224 t
.Errorf("#%d got %s want %s", i
, x
.RatString(), test
.out
)
229 var floatStringTests
= []struct {
240 {"-0.05", 1, "-0.1"},
244 {"-1/3", 3, "-0.333"},
245 {"-2/3", 4, "-0.6667"},
247 {"0.999", 2, "1.00"},
253 func TestFloatString(t
*testing
.T
) {
254 for i
, test
:= range floatStringTests
{
255 x
, _
:= new(Rat
).SetString(test
.in
)
257 if x
.FloatString(test
.prec
) != test
.out
{
258 t
.Errorf("#%d got %s want %s", i
, x
.FloatString(test
.prec
), test
.out
)
263 // Test inputs to Rat.SetString. The prefix "long:" causes the test
264 // to be skipped except in -long mode. (The threshold is about 500us.)
265 var float64inputs
= []string{
266 // Constants plundered from strconv/testfp.txt.
268 // Table 1: Stress Inputs for Conversion to 53-bit Binary, < 1/2 ULP
281 "3142213164987e-294",
282 "46202199371337e-072",
283 "231010996856685e-073",
284 "9324754620109615e+212",
285 "78459735791271921e+049",
286 "272104041512242479e+200",
287 "6802601037806061975e+198",
288 "20505426358836677347e-221",
289 "836168422905420598437e-234",
290 "4891559871276714924261e+222",
292 // Table 2: Stress Inputs for Conversion to 53-bit Binary, > 1/2 ULP
305 "2335141086879e+218",
306 "36167929443327e-159",
307 "609610927149051e-255",
308 "3743626360493413e-165",
309 "94080055902682397e-242",
310 "899810892172646163e+283",
311 "7120190517612959703e+120",
312 "25188282901709339043e-252",
313 "308984926168550152811e-052",
314 "6372891218502368041059e+064",
316 // Table 14: Stress Inputs for Conversion to 24-bit Binary, <1/2 ULP
330 // Table 15: Stress Inputs for Conversion to 24-bit Binary, >1/2 ULP
344 // Constants plundered from strconv/atof_test.go.
351 "100000000000000000000000",
354 "99999999999999974834176",
355 "100000000000000000000001",
356 "100000000000000008388608",
357 "100000000000000016777215",
358 "100000000000000016777216",
361 "-0", // NB: exception made for this input
366 "1.7976931348623157e308",
367 "-1.7976931348623157e308",
368 // next float64 - too large
369 "1.7976931348623159e308",
370 "-1.7976931348623159e308",
371 // the border is ...158079
373 "1.7976931348623158e308",
374 "-1.7976931348623158e308",
375 // borderline - too large
376 "1.797693134862315808e308",
377 "-1.797693134862315808e308",
379 // a little too large
409 // way too small, negative
413 // try to overflow exponent
414 // [Disabled: too slow and memory-hungry with rationals.]
417 // "1e-18446744073709551616",
418 // "1e+18446744073709551616",
420 // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
421 "2.2250738585072012e-308",
422 // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
423 "2.2250738585072011e-308",
425 // A very large number (initially wrongly parsed by the fast algorithm).
426 "4.630813248087435e+307",
428 // A different kind of very large number.
429 "22.222222222222222",
430 "long:2." + strings
.Repeat("2", 4000) + "e+1",
432 // Exactly halfway between 1 and math.Nextafter(1, 2).
433 // Round to even (down).
434 "1.00000000000000011102230246251565404236316680908203125",
435 // Slightly lower; still round down.
436 "1.00000000000000011102230246251565404236316680908203124",
437 // Slightly higher; round up.
438 "1.00000000000000011102230246251565404236316680908203126",
439 // Slightly higher, but you have to read all the way to the end.
440 "long:1.00000000000000011102230246251565404236316680908203125" + strings
.Repeat("0", 10000) + "1",
442 // Smallest denormal, 2^(-1022-52)
443 "4.940656458412465441765687928682213723651e-324",
444 // Half of smallest denormal, 2^(-1022-53)
445 "2.470328229206232720882843964341106861825e-324",
446 // A little more than the exact half of smallest denormal
447 // 2^-1075 + 2^-1100. (Rounds to 1p-1074.)
448 "2.470328302827751011111470718709768633275e-324",
449 // The exact halfway between smallest normal and largest denormal:
450 // 2^-1022 - 2^-1075. (Rounds to 2^-1022.)
451 "2.225073858507201136057409796709131975935e-308",
453 "1152921504606846975", // 1<<60 - 1
454 "-1152921504606846975", // -(1<<60 - 1)
455 "1152921504606846977", // 1<<60 + 1
456 "-1152921504606846977", // -(1<<60 + 1)
461 // isFinite reports whether f represents a finite rational value.
462 // It is equivalent to !math.IsNan(f) && !math.IsInf(f, 0).
463 func isFinite(f
float64) bool {
464 return math
.Abs(f
) <= math
.MaxFloat64
467 func TestFloat32SpecialCases(t
*testing
.T
) {
468 for _
, input
:= range float64inputs
{
469 if strings
.HasPrefix(input
, "long:") {
473 input
= input
[len("long:"):]
476 r
, ok
:= new(Rat
).SetString(input
)
478 t
.Errorf("Rat.SetString(%q) failed", input
)
481 f
, exact
:= r
.Float32()
483 // 1. Check string -> Rat -> float32 conversions are
484 // consistent with strconv.ParseFloat.
485 // Skip this check if the input uses "a/b" rational syntax.
486 if !strings
.Contains(input
, "/") {
487 e64
, _
:= strconv
.ParseFloat(input
, 32)
490 // Careful: negative Rats too small for
491 // float64 become -0, but Rat obviously cannot
492 // preserve the sign from SetString("-0").
494 case math
.Float32bits(e
) == math
.Float32bits(f
):
495 // Ok: bitwise equal.
496 case f
== 0 && r
.Num().BitLen() == 0:
497 // Ok: Rat(0) is equivalent to both +/- float64(0).
499 t
.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input
, e
, e
, f
, f
, f
-e
)
503 if !isFinite(float64(f
)) {
507 // 2. Check f is best approximation to r.
508 if !checkIsBestApprox32(t
, f
, r
) {
509 // Append context information.
510 t
.Errorf("(input was %q)", input
)
513 // 3. Check f->R->f roundtrip is non-lossy.
514 checkNonLossyRoundtrip32(t
, f
)
516 // 4. Check exactness using slow algorithm.
517 if wasExact
:= new(Rat
).SetFloat64(float64(f
)).Cmp(r
) == 0; wasExact
!= exact
{
518 t
.Errorf("Rat.SetString(%q).Float32().exact = %t, want %t", input
, exact
, wasExact
)
523 func TestFloat64SpecialCases(t
*testing
.T
) {
524 for _
, input
:= range float64inputs
{
525 if strings
.HasPrefix(input
, "long:") {
529 input
= input
[len("long:"):]
532 r
, ok
:= new(Rat
).SetString(input
)
534 t
.Errorf("Rat.SetString(%q) failed", input
)
537 f
, exact
:= r
.Float64()
539 // 1. Check string -> Rat -> float64 conversions are
540 // consistent with strconv.ParseFloat.
541 // Skip this check if the input uses "a/b" rational syntax.
542 if !strings
.Contains(input
, "/") {
543 e
, _
:= strconv
.ParseFloat(input
, 64)
545 // Careful: negative Rats too small for
546 // float64 become -0, but Rat obviously cannot
547 // preserve the sign from SetString("-0").
549 case math
.Float64bits(e
) == math
.Float64bits(f
):
550 // Ok: bitwise equal.
551 case f
== 0 && r
.Num().BitLen() == 0:
552 // Ok: Rat(0) is equivalent to both +/- float64(0).
554 t
.Errorf("strconv.ParseFloat(%q) = %g (%b), want %g (%b); delta = %g", input
, e
, e
, f
, f
, f
-e
)
562 // 2. Check f is best approximation to r.
563 if !checkIsBestApprox64(t
, f
, r
) {
564 // Append context information.
565 t
.Errorf("(input was %q)", input
)
568 // 3. Check f->R->f roundtrip is non-lossy.
569 checkNonLossyRoundtrip64(t
, f
)
571 // 4. Check exactness using slow algorithm.
572 if wasExact
:= new(Rat
).SetFloat64(f
).Cmp(r
) == 0; wasExact
!= exact
{
573 t
.Errorf("Rat.SetString(%q).Float64().exact = %t, want %t", input
, exact
, wasExact
)
578 func TestIssue31184(t
*testing
.T
) {
580 for _
, want
:= range []string{
586 got
:= x
.FloatString(3)
588 t
.Errorf("got %s, want %s", got
, want
)
593 func TestIssue45910(t
*testing
.T
) {
595 for _
, test
:= range []struct {
599 {"1e-1000001", false},
600 {"1e-1000000", true},
601 {"1e+1000000", true},
602 {"1e+1000001", false},
604 {"0p1000000000000", true},
605 {"1p-10000001", false},
606 {"1p-10000000", true},
607 {"1p+10000000", true},
608 {"1p+10000001", false},
609 {"1.770p02041010010011001001", false}, // test case from issue
611 _
, got
:= x
.SetString(test
.input
)
612 if got
!= test
.want
{
613 t
.Errorf("SetString(%s) got ok = %v; want %v", test
.input
, got
, test
.want
)