feature_stream_float.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package jsoniter
  2. import (
  3. "math"
  4. "strconv"
  5. )
  6. var _POW10 []uint64
  7. func init() {
  8. _POW10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
  9. }
  10. func (stream *Stream) WriteFloat32(val float32) {
  11. abs := math.Abs(float64(val))
  12. fmt := byte('f')
  13. // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
  14. if abs != 0 {
  15. if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
  16. fmt = 'e'
  17. }
  18. }
  19. stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 32))
  20. }
  21. func (stream *Stream) WriteFloat32Lossy(val float32) {
  22. if val < 0 {
  23. stream.writeByte('-')
  24. val = -val
  25. }
  26. if val > 0x4ffffff {
  27. stream.WriteFloat32(val)
  28. return
  29. }
  30. precision := 6
  31. exp := uint64(1000000) // 6
  32. lval := uint64(float64(val)*float64(exp) + 0.5)
  33. stream.WriteUint64(lval / exp)
  34. fval := lval % exp
  35. if fval == 0 {
  36. return
  37. }
  38. stream.writeByte('.')
  39. stream.ensure(10)
  40. for p := precision - 1; p > 0 && fval < _POW10[p]; p-- {
  41. stream.writeByte('0')
  42. }
  43. stream.WriteUint64(fval)
  44. for stream.buf[stream.n-1] == '0' {
  45. stream.n--
  46. }
  47. }
  48. func (stream *Stream) WriteFloat64(val float64) {
  49. abs := math.Abs(val)
  50. fmt := byte('f')
  51. // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
  52. if abs != 0 {
  53. if abs < 1e-6 || abs >= 1e21 {
  54. fmt = 'e'
  55. }
  56. }
  57. stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 64))
  58. }
  59. func (stream *Stream) WriteFloat64Lossy(val float64) {
  60. if val < 0 {
  61. stream.writeByte('-')
  62. val = -val
  63. }
  64. if val > 0x4ffffff {
  65. stream.WriteFloat64(val)
  66. return
  67. }
  68. precision := 6
  69. exp := uint64(1000000) // 6
  70. lval := uint64(val*float64(exp) + 0.5)
  71. stream.WriteUint64(lval / exp)
  72. fval := lval % exp
  73. if fval == 0 {
  74. return
  75. }
  76. stream.writeByte('.')
  77. stream.ensure(10)
  78. for p := precision - 1; p > 0 && fval < _POW10[p]; p-- {
  79. stream.writeByte('0')
  80. }
  81. stream.WriteUint64(fval)
  82. for stream.buf[stream.n-1] == '0' {
  83. stream.n--
  84. }
  85. }