Преглед на файлове

fix write float compatibility

Tao Wen преди 8 години
родител
ревизия
c009421781
променени са 3 файла, в които са добавени 28 реда и са изтрити 6 реда
  1. 21 4
      feature_stream_float.go
  2. 1 0
      jsoniter_1dot8_only_test.go
  3. 6 2
      jsoniter_float_test.go

+ 21 - 4
feature_stream_float.go

@@ -2,6 +2,7 @@ package jsoniter
 
 import (
 	"strconv"
+	"math"
 )
 
 var _POW10 []uint64
@@ -11,7 +12,15 @@ func init() {
 }
 
 func (stream *Stream) WriteFloat32(val float32) {
-	stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
+	abs := math.Abs(float64(val))
+	fmt := byte('f')
+	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+	if abs != 0 {
+		if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
+			fmt = 'e'
+		}
+	}
+	stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 32))
 }
 
 func (stream *Stream) WriteFloat32Lossy(val float32) {
@@ -20,7 +29,7 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
 		val = -val
 	}
 	if val > 0x4ffffff {
-		stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 32))
+		stream.WriteFloat32(val)
 		return
 	}
 	precision := 6
@@ -43,7 +52,15 @@ func (stream *Stream) WriteFloat32Lossy(val float32) {
 }
 
 func (stream *Stream) WriteFloat64(val float64) {
-	stream.WriteRaw(strconv.FormatFloat(float64(val), 'f', -1, 64))
+	abs := math.Abs(val)
+	fmt := byte('f')
+	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+	if abs != 0 {
+		if abs < 1e-6 || abs >= 1e21 {
+			fmt = 'e'
+		}
+	}
+	stream.WriteRaw(strconv.FormatFloat(float64(val), fmt, -1, 64))
 }
 
 func (stream *Stream) WriteFloat64Lossy(val float64) {
@@ -52,7 +69,7 @@ func (stream *Stream) WriteFloat64Lossy(val float64) {
 		val = -val
 	}
 	if val > 0x4ffffff {
-		stream.WriteRaw(strconv.FormatFloat(val, 'f', -1, 64))
+		stream.WriteFloat64(val)
 		return
 	}
 	precision := 6

+ 1 - 0
jsoniter_1dot8_only_test.go

@@ -1,4 +1,5 @@
 // +build go1.8
+
 package jsoniter
 
 import (

+ 6 - 2
jsoniter_float_test.go

@@ -85,7 +85,9 @@ func Test_write_float32(t *testing.T) {
 			stream.WriteFloat32Lossy(val)
 			stream.Flush()
 			should.Nil(stream.Error)
-			should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
+			output, err := json.Marshal(val)
+			should.Nil(err)
+			should.Equal(string(output), buf.String())
 		})
 		t.Run(fmt.Sprintf("%v", val), func(t *testing.T) {
 			should := require.New(t)
@@ -94,7 +96,9 @@ func Test_write_float32(t *testing.T) {
 			stream.WriteVal(val)
 			stream.Flush()
 			should.Nil(stream.Error)
-			should.Equal(strconv.FormatFloat(float64(val), 'f', -1, 32), buf.String())
+			output, err := json.Marshal(val)
+			should.Nil(err)
+			should.Equal(string(output), buf.String())
 		})
 	}
 	should := require.New(t)