Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package big | 5 package big |
6 | 6 |
7 import ( | 7 import ( |
8 "bufio" | |
8 "bytes" | 9 "bytes" |
9 "encoding/gob" | 10 "encoding/gob" |
10 "fmt" | 11 "fmt" |
12 "io" | |
13 "math" | |
14 "os" | |
15 "strconv" | |
16 "strings" | |
11 "testing" | 17 "testing" |
12 ) | 18 ) |
13 | 19 |
14 func TestZeroRat(t *testing.T) { | 20 func TestZeroRat(t *testing.T) { |
15 var x, y, z Rat | 21 var x, y, z Rat |
16 y.SetFrac64(0, 42) | 22 y.SetFrac64(0, 42) |
17 | 23 |
18 if x.Cmp(&y) != 0 { | 24 if x.Cmp(&y) != 0 { |
19 t.Errorf("x and y should be both equal and zero") | 25 t.Errorf("x and y should be both equal and zero") |
20 } | 26 } |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 // 3) changing the numerator/denominator of a Rat changes the Rat | 495 // 3) changing the numerator/denominator of a Rat changes the Rat |
490 x.SetFrac(a, b) | 496 x.SetFrac(a, b) |
491 a = x.Num() | 497 a = x.Num() |
492 b = x.Denom() | 498 b = x.Denom() |
493 a.SetInt64(5) | 499 a.SetInt64(5) |
494 b.SetInt64(3) | 500 b.SetInt64(3) |
495 if x.Cmp(q53) != 0 { | 501 if x.Cmp(q53) != 0 { |
496 t.Errorf("3) got %s want %s", x, q53) | 502 t.Errorf("3) got %s want %s", x, q53) |
497 } | 503 } |
498 } | 504 } |
505 | |
506 // This test uses the same file of input data as strconv_test. | |
507 func TestIEEE754(t *testing.T) { | |
508 // TODO(adonovan): is this ok? Or should I copy the file, or even | |
remyoudompheng
2012/12/13 07:37:38
I'm not sure testfp.txt is a good input file for t
rsc
2012/12/13 14:41:58
You can read the file directly, that's fine. As fo
adonovan
2012/12/14 23:22:43
Done.
| |
509 // move the constants into the code? | |
510 f, err := os.Open("../../strconv/testfp.txt") | |
511 if err != nil { | |
512 t.Fatal("testfp: open ../../strconv/testfp.txt:", err) | |
513 } | |
514 defer f.Close() | |
515 | |
516 b := bufio.NewReader(f) | |
517 | |
518 lineno := 0 | |
519 for { | |
520 line, err2 := b.ReadString('\n') | |
521 if err2 == io.EOF { | |
522 break | |
523 } | |
524 if err2 != nil { | |
525 t.Fatal("testfp: read testfp.txt: " + err2.Error()) | |
526 } | |
527 line = line[0 : len(line)-1] | |
528 lineno++ | |
529 if len(line) == 0 || line[0] == '#' { | |
530 continue | |
531 } | |
532 a := strings.Split(line, " ") | |
533 if len(a) != 4 { | |
534 t.Error("testfp.txt:", lineno, ": wrong field count") | |
535 continue | |
536 } | |
537 var v float64 | |
538 switch a[0] { | |
539 case "float32", "float64": | |
540 var ok bool | |
541 v, ok = myatof64(a[2]) | |
542 if !ok { | |
543 t.Error("testfp.txt:", lineno, ": cannot atof64" , a[2]) | |
544 continue | |
545 } | |
546 | |
547 var r Rat | |
548 r.SetFloat64(v) | |
549 v2, exact := r.Float64() | |
550 if v != v2 { | |
551 t.Error("testfp.txt:", lineno, ": float64 <=> Ra t roundtrip yielded different value for", a[2], "epsilon=", v2-v) | |
552 continue | |
553 } | |
554 if !exact { | |
555 t.Error("testfp.txt:", lineno, ": float64 <=> Ra t roundtrip was inexact for", a[2]) | |
556 continue | |
557 } | |
558 } | |
559 | |
560 } | |
561 | |
562 // Some rationals are not exactly representable by IEEE 754. | |
563 inexact := []struct { | |
564 rat string | |
565 expected float64 | |
566 }{ | |
567 {"1/3", 1.0 / 3}, | |
568 {"1.23456788e1234", math.Inf(+1)}, | |
569 {"-1.23456788e1234", math.Inf(-1)}, | |
570 {"1.23456788e-1234", 0.0}, | |
571 {"-1.23456788e-1234", 0.0}, | |
572 } | |
573 for _, s := range inexact { | |
574 rat, ok := new(Rat).SetString(s.rat) | |
575 if !ok { | |
576 t.Error("Rat.SetString(\"" + s.rat + "\") failed") | |
577 } | |
578 v, exact := rat.Float64() | |
579 if exact { | |
580 t.Error("Rat.Float64() returned exact=true for inexact r ational", s.rat, v) | |
581 } | |
582 if v != s.expected { | |
583 t.Error("Rat.Float64() returned incorrect value", s.rat, v, s.expected, "delta=", v-s.expected) | |
584 } | |
585 } | |
586 } | |
587 | |
588 // TODO(adonovan): plundered from strconv_test. What to do? | |
589 func pow2(i int) float64 { | |
590 switch { | |
591 case i < 0: | |
592 return 1 / pow2(-i) | |
593 case i == 0: | |
594 return 1 | |
595 case i == 1: | |
596 return 2 | |
597 } | |
598 return pow2(i/2) * pow2(i-i/2) | |
599 } | |
600 | |
601 // TODO(adonovan): plundered from strconv_test. What to do? | |
602 // | |
603 // Wrapper around strconv.ParseFloat(x, 64). Handles dddddp+ddd (binary exponen t) | |
604 // itself, passes the rest on to strconv.ParseFloat. | |
605 func myatof64(s string) (f float64, ok bool) { | |
606 a := strings.SplitN(s, "p", 2) | |
607 if len(a) == 2 { | |
608 n, err := strconv.ParseInt(a[0], 10, 64) | |
609 if err != nil { | |
610 return 0, false | |
611 } | |
612 e, err1 := strconv.Atoi(a[1]) | |
613 if err1 != nil { | |
614 println("bad e", a[1]) | |
615 return 0, false | |
616 } | |
617 v := float64(n) | |
618 // We expect that v*pow2(e) fits in a float64, | |
619 // but pow2(e) by itself may not. Be careful. | |
620 if e <= -1000 { | |
621 v *= pow2(-1000) | |
622 e += 1000 | |
623 for e < 0 { | |
624 v /= 2 | |
625 e++ | |
626 } | |
627 return v, true | |
628 } | |
629 if e >= 1000 { | |
630 v *= pow2(1000) | |
631 e -= 1000 | |
632 for e > 0 { | |
633 v *= 2 | |
634 e-- | |
635 } | |
636 return v, true | |
637 } | |
638 return v * pow2(e), true | |
639 } | |
640 f1, err := strconv.ParseFloat(s, 64) | |
641 if err != nil { | |
642 return 0, false | |
643 } | |
644 return f1, true | |
645 } | |
OLD | NEW |