...

Source file src/github.com/json-iterator/go/stream_float.go

Documentation: github.com/json-iterator/go

     1  package jsoniter
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strconv"
     7  )
     8  
     9  var pow10 []uint64
    10  
    11  func init() {
    12  	pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
    13  }
    14  
    15  // WriteFloat32 write float32 to stream
    16  func (stream *Stream) WriteFloat32(val float32) {
    17  	if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
    18  		stream.Error = fmt.Errorf("unsupported value: %f", val)
    19  		return
    20  	}
    21  	abs := math.Abs(float64(val))
    22  	fmt := byte('f')
    23  	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
    24  	if abs != 0 {
    25  		if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
    26  			fmt = 'e'
    27  		}
    28  	}
    29  	stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32)
    30  }
    31  
    32  // WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster
    33  func (stream *Stream) WriteFloat32Lossy(val float32) {
    34  	if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
    35  		stream.Error = fmt.Errorf("unsupported value: %f", val)
    36  		return
    37  	}
    38  	if val < 0 {
    39  		stream.writeByte('-')
    40  		val = -val
    41  	}
    42  	if val > 0x4ffffff {
    43  		stream.WriteFloat32(val)
    44  		return
    45  	}
    46  	precision := 6
    47  	exp := uint64(1000000) // 6
    48  	lval := uint64(float64(val)*float64(exp) + 0.5)
    49  	stream.WriteUint64(lval / exp)
    50  	fval := lval % exp
    51  	if fval == 0 {
    52  		return
    53  	}
    54  	stream.writeByte('.')
    55  	for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
    56  		stream.writeByte('0')
    57  	}
    58  	stream.WriteUint64(fval)
    59  	for stream.buf[len(stream.buf)-1] == '0' {
    60  		stream.buf = stream.buf[:len(stream.buf)-1]
    61  	}
    62  }
    63  
    64  // WriteFloat64 write float64 to stream
    65  func (stream *Stream) WriteFloat64(val float64) {
    66  	if math.IsInf(val, 0) || math.IsNaN(val) {
    67  		stream.Error = fmt.Errorf("unsupported value: %f", val)
    68  		return
    69  	}
    70  	abs := math.Abs(val)
    71  	fmt := byte('f')
    72  	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
    73  	if abs != 0 {
    74  		if abs < 1e-6 || abs >= 1e21 {
    75  			fmt = 'e'
    76  		}
    77  	}
    78  	stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64)
    79  }
    80  
    81  // WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster
    82  func (stream *Stream) WriteFloat64Lossy(val float64) {
    83  	if math.IsInf(val, 0) || math.IsNaN(val) {
    84  		stream.Error = fmt.Errorf("unsupported value: %f", val)
    85  		return
    86  	}
    87  	if val < 0 {
    88  		stream.writeByte('-')
    89  		val = -val
    90  	}
    91  	if val > 0x4ffffff {
    92  		stream.WriteFloat64(val)
    93  		return
    94  	}
    95  	precision := 6
    96  	exp := uint64(1000000) // 6
    97  	lval := uint64(val*float64(exp) + 0.5)
    98  	stream.WriteUint64(lval / exp)
    99  	fval := lval % exp
   100  	if fval == 0 {
   101  		return
   102  	}
   103  	stream.writeByte('.')
   104  	for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
   105  		stream.writeByte('0')
   106  	}
   107  	stream.WriteUint64(fval)
   108  	for stream.buf[len(stream.buf)-1] == '0' {
   109  		stream.buf = stream.buf[:len(stream.buf)-1]
   110  	}
   111  }
   112  

View as plain text