fp_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // Copyright 2009 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.
  4. package strconv_test
  5. import (
  6. "bufio"
  7. "fmt"
  8. "os"
  9. "strconv"
  10. "strings"
  11. "testing"
  12. )
  13. func pow2(i int) float64 {
  14. switch {
  15. case i < 0:
  16. return 1 / pow2(-i)
  17. case i == 0:
  18. return 1
  19. case i == 1:
  20. return 2
  21. }
  22. return pow2(i/2) * pow2(i-i/2)
  23. }
  24. // Wrapper around strconv.ParseFloat(x, 64). Handles dddddp+ddd (binary exponent)
  25. // itself, passes the rest on to strconv.ParseFloat.
  26. func myatof64(s string) (f float64, ok bool) {
  27. a := strings.SplitN(s, "p", 2)
  28. if len(a) == 2 {
  29. n, err := strconv.ParseInt(a[0], 10, 64)
  30. if err != nil {
  31. return 0, false
  32. }
  33. e, err1 := strconv.Atoi(a[1])
  34. if err1 != nil {
  35. println("bad e", a[1])
  36. return 0, false
  37. }
  38. v := float64(n)
  39. // We expect that v*pow2(e) fits in a float64,
  40. // but pow2(e) by itself may not. Be careful.
  41. if e <= -1000 {
  42. v *= pow2(-1000)
  43. e += 1000
  44. for e < 0 {
  45. v /= 2
  46. e++
  47. }
  48. return v, true
  49. }
  50. if e >= 1000 {
  51. v *= pow2(1000)
  52. e -= 1000
  53. for e > 0 {
  54. v *= 2
  55. e--
  56. }
  57. return v, true
  58. }
  59. return v * pow2(e), true
  60. }
  61. f1, err := strconv.ParseFloat(s, 64)
  62. if err != nil {
  63. return 0, false
  64. }
  65. return f1, true
  66. }
  67. // Wrapper around strconv.ParseFloat(x, 32). Handles dddddp+ddd (binary exponent)
  68. // itself, passes the rest on to strconv.ParseFloat.
  69. func myatof32(s string) (f float32, ok bool) {
  70. a := strings.SplitN(s, "p", 2)
  71. if len(a) == 2 {
  72. n, err := strconv.Atoi(a[0])
  73. if err != nil {
  74. println("bad n", a[0])
  75. return 0, false
  76. }
  77. e, err1 := strconv.Atoi(a[1])
  78. if err1 != nil {
  79. println("bad p", a[1])
  80. return 0, false
  81. }
  82. return float32(float64(n) * pow2(e)), true
  83. }
  84. f64, err1 := strconv.ParseFloat(s, 32)
  85. f1 := float32(f64)
  86. if err1 != nil {
  87. return 0, false
  88. }
  89. return f1, true
  90. }
  91. func TestFp(t *testing.T) {
  92. f, err := os.Open("testdata/testfp.txt")
  93. if err != nil {
  94. t.Fatal("testfp: open testdata/testfp.txt:", err)
  95. }
  96. defer f.Close()
  97. s := bufio.NewScanner(f)
  98. for lineno := 1; s.Scan(); lineno++ {
  99. line := s.Text()
  100. if len(line) == 0 || line[0] == '#' {
  101. continue
  102. }
  103. a := strings.Split(line, " ")
  104. if len(a) != 4 {
  105. t.Error("testdata/testfp.txt:", lineno, ": wrong field count")
  106. continue
  107. }
  108. var s string
  109. var v float64
  110. switch a[0] {
  111. case "float64":
  112. var ok bool
  113. v, ok = myatof64(a[2])
  114. if !ok {
  115. t.Error("testdata/testfp.txt:", lineno, ": cannot atof64 ", a[2])
  116. continue
  117. }
  118. s = fmt.Sprintf(a[1], v)
  119. case "float32":
  120. v1, ok := myatof32(a[2])
  121. if !ok {
  122. t.Error("testdata/testfp.txt:", lineno, ": cannot atof32 ", a[2])
  123. continue
  124. }
  125. s = fmt.Sprintf(a[1], v1)
  126. v = float64(v1)
  127. }
  128. if s != a[3] {
  129. t.Error("testdata/testfp.txt:", lineno, ": ", a[0], " ", a[1], " ", a[2], " (", v, ") ",
  130. "want ", a[3], " got ", s)
  131. }
  132. }
  133. if s.Err() != nil {
  134. t.Fatal("testfp: read testdata/testfp.txt: ", s.Err())
  135. }
  136. }