float_test.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package strconv // import "github.com/tdewolff/parse/strconv"
  2. import (
  3. "fmt"
  4. "math"
  5. "math/rand"
  6. "strconv"
  7. "testing"
  8. "github.com/tdewolff/test"
  9. )
  10. func TestParseFloat(t *testing.T) {
  11. floatTests := []struct {
  12. f string
  13. expected float64
  14. }{
  15. {"5", 5},
  16. {"5.1", 5.1},
  17. {"-5.1", -5.1},
  18. {"5.1e-2", 5.1e-2},
  19. {"5.1e+2", 5.1e+2},
  20. {"0.0e1", 0.0e1},
  21. {"18446744073709551620", 18446744073709551620.0},
  22. {"1e23", 1e23},
  23. // TODO: hard to test due to float imprecision
  24. // {"1.7976931348623e+308", 1.7976931348623e+308)
  25. // {"4.9406564584124e-308", 4.9406564584124e-308)
  26. }
  27. for _, tt := range floatTests {
  28. f, n := ParseFloat([]byte(tt.f))
  29. test.That(t, n == len(tt.f), "parsed", n, "characters instead for", tt.f)
  30. test.That(t, f == tt.expected, "return", tt.expected, "for", tt.f)
  31. }
  32. }
  33. func TestAppendFloat(t *testing.T) {
  34. floatTests := []struct {
  35. f float64
  36. prec int
  37. expected string
  38. }{
  39. {0, 6, "0"},
  40. {1, 6, "1"},
  41. {9, 6, "9"},
  42. {9.99999, 6, "9.99999"},
  43. {123, 6, "123"},
  44. {0.123456, 6, ".123456"},
  45. {0.066, 6, ".066"},
  46. {0.0066, 6, ".0066"},
  47. {12e2, 6, "1200"},
  48. {12e3, 6, "12e3"},
  49. {0.1, 6, ".1"},
  50. {0.001, 6, ".001"},
  51. {0.0001, 6, "1e-4"},
  52. {-1, 6, "-1"},
  53. {-123, 6, "-123"},
  54. {-123.456, 6, "-123.456"},
  55. {-12e3, 6, "-12e3"},
  56. {-0.1, 6, "-.1"},
  57. {-0.0001, 6, "-1e-4"},
  58. {0.000100009, 10, "100009e-9"},
  59. {0.0001000009, 10, "1.000009e-4"},
  60. {1e18, 0, "1e18"},
  61. //{1e19, 0, "1e19"},
  62. //{1e19, 18, "1e19"},
  63. {1e1, 0, "10"},
  64. {1e2, 1, "100"},
  65. {1e3, 2, "1e3"},
  66. {1e10, -1, "1e10"},
  67. {1e15, -1, "1e15"},
  68. {1e-5, 6, "1e-5"},
  69. {math.NaN(), 0, ""},
  70. {math.Inf(1), 0, ""},
  71. {math.Inf(-1), 0, ""},
  72. {0, 19, ""},
  73. {.000923361977200859392, -1, "9.23361977200859392e-4"},
  74. }
  75. for _, tt := range floatTests {
  76. f, _ := AppendFloat([]byte{}, tt.f, tt.prec)
  77. test.String(t, string(f), tt.expected, "for", tt.f)
  78. }
  79. b := make([]byte, 0, 22)
  80. AppendFloat(b, 12.34, -1)
  81. test.String(t, string(b[:5]), "12.34", "in buffer")
  82. }
  83. ////////////////////////////////////////////////////////////////
  84. func TestAppendFloatRandom(t *testing.T) {
  85. N := int(1e6)
  86. if testing.Short() {
  87. N = 0
  88. }
  89. r := rand.New(rand.NewSource(99))
  90. //prec := 10
  91. for i := 0; i < N; i++ {
  92. f := r.ExpFloat64()
  93. //f = math.Floor(f*float64(prec)) / float64(prec)
  94. b, _ := AppendFloat([]byte{}, f, -1)
  95. f2, _ := strconv.ParseFloat(string(b), 64)
  96. if math.Abs(f-f2) > 1e-6 {
  97. fmt.Println("Bad:", f, "!=", f2, "in", string(b))
  98. }
  99. }
  100. }
  101. func BenchmarkFloatToBytes1(b *testing.B) {
  102. r := []byte{} //make([]byte, 10)
  103. f := 123.456
  104. for i := 0; i < b.N; i++ {
  105. r = strconv.AppendFloat(r[:0], f, 'g', 6, 64)
  106. }
  107. }
  108. func BenchmarkFloatToBytes2(b *testing.B) {
  109. r := make([]byte, 10)
  110. f := 123.456
  111. for i := 0; i < b.N; i++ {
  112. r, _ = AppendFloat(r[:0], f, 6)
  113. }
  114. }
  115. func BenchmarkModf1(b *testing.B) {
  116. f := 123.456
  117. x := 0.0
  118. for i := 0; i < b.N; i++ {
  119. a, b := math.Modf(f)
  120. x += a + b
  121. }
  122. }
  123. func BenchmarkModf2(b *testing.B) {
  124. f := 123.456
  125. x := 0.0
  126. for i := 0; i < b.N; i++ {
  127. a := float64(int64(f))
  128. b := f - a
  129. x += a + b
  130. }
  131. }
  132. func BenchmarkPrintInt1(b *testing.B) {
  133. X := int64(123456789)
  134. n := LenInt(X)
  135. r := make([]byte, n)
  136. for i := 0; i < b.N; i++ {
  137. x := X
  138. j := n
  139. for x > 0 {
  140. j--
  141. r[j] = '0' + byte(x%10)
  142. x /= 10
  143. }
  144. }
  145. }
  146. func BenchmarkPrintInt2(b *testing.B) {
  147. X := int64(123456789)
  148. n := LenInt(X)
  149. r := make([]byte, n)
  150. for i := 0; i < b.N; i++ {
  151. x := X
  152. j := n
  153. for x > 0 {
  154. j--
  155. newX := x / 10
  156. r[j] = '0' + byte(x-10*newX)
  157. x = newX
  158. }
  159. }
  160. }
  161. var int64pow10 = []int64{
  162. 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
  163. 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18,
  164. }
  165. func BenchmarkPrintInt3(b *testing.B) {
  166. X := int64(123456789)
  167. n := LenInt(X)
  168. r := make([]byte, n)
  169. for i := 0; i < b.N; i++ {
  170. x := X
  171. j := 0
  172. for j < n {
  173. pow := int64pow10[n-j-1]
  174. tmp := x / pow
  175. r[j] = '0' + byte(tmp)
  176. j++
  177. x -= tmp * pow
  178. }
  179. }
  180. }