feature_stream_float.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package jsoniter
  2. import (
  3. "strconv"
  4. "unsafe"
  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. stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
  12. }
  13. func (stream *Stream) WriteFloat32Lossy(val float32) {
  14. if val < 0 {
  15. stream.writeByte('-')
  16. val = -val
  17. }
  18. if val > 0x4ffffff {
  19. stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
  20. return
  21. }
  22. precision := 6
  23. exp := uint64(1000000) // 6
  24. lval := uint64(float64(val)*float64(exp) + 0.5)
  25. stream.WriteUint64(lval / exp)
  26. fval := lval % exp
  27. if fval == 0 {
  28. return
  29. }
  30. stream.writeByte('.')
  31. stream.ensure(10)
  32. for p := precision - 1; p > 0 && fval < POW10[p]; p-- {
  33. stream.writeByte('0')
  34. }
  35. stream.WriteUint64(fval)
  36. for stream.buf[stream.n-1] == '0' {
  37. stream.n--
  38. }
  39. }
  40. func (stream *Stream) WriteFloat64(val float64) {
  41. stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 64))
  42. }
  43. func (stream *Stream) WriteFloat64Lossy(val float64) {
  44. if val < 0 {
  45. stream.writeByte('-')
  46. val = -val
  47. }
  48. if val > 0x4ffffff {
  49. stream.WriteRaw(strconv.FormatFloat(val, 'f', -1, 64))
  50. return
  51. }
  52. precision := 6
  53. exp := uint64(1000000) // 6
  54. lval := uint64(val*float64(exp) + 0.5)
  55. stream.WriteUint64(lval / exp)
  56. fval := lval % exp
  57. if fval == 0 {
  58. return
  59. }
  60. stream.writeByte('.')
  61. stream.ensure(10)
  62. for p := precision - 1; p > 0 && fval < POW10[p]; p-- {
  63. stream.writeByte('0')
  64. }
  65. stream.WriteUint64(fval)
  66. for stream.buf[stream.n-1] == '0' {
  67. stream.n--
  68. }
  69. }
  70. // EnableLossyFloatMarshalling keeps 10**(-6) precision
  71. // for float variables for better performance.
  72. func EnableLossyFloatMarshalling() {
  73. // for better performance
  74. RegisterTypeEncoder("float32", func(ptr unsafe.Pointer, stream *Stream) {
  75. val := *((*float32)(ptr))
  76. stream.WriteFloat32Lossy(val)
  77. })
  78. RegisterTypeEncoder("float64", func(ptr unsafe.Pointer, stream *Stream) {
  79. val := *((*float64)(ptr))
  80. stream.WriteFloat64Lossy(val)
  81. })
  82. }