-
Notifications
You must be signed in to change notification settings - Fork 8
/
float.go
137 lines (121 loc) · 2.91 KB
/
float.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package cvt
import (
"encoding/json"
"fmt"
"math"
"strconv"
"time"
)
// Float64 convert an interface to a float64 type, with default value
func Float64(v interface{}, def ...float64) float64 {
if v, err := Float64E(v); err == nil {
return v
}
if len(def) > 0 {
return def[0]
}
return 0
}
// Float64P convert and store in a new float64 value, and returns a pointer to it
func Float64P(v interface{}, def ...float64) *float64 {
i := Float64(v, def...)
return &i
}
// Float64E convert an interface to a float64 type
func Float64E(val interface{}) (float64, error) {
v, e := convFloat64E(val)
if e := catch("float64", val, e); e != nil {
return 0, e
}
return v, nil
}
func convFloat64E(val interface{}) (float64, error) {
// direct type(for improve performance)
switch vv := val.(type) {
case nil:
return 0, nil
case bool:
if vv {
return 1, nil
}
return 0, nil
case string:
vvv, err := strconv.ParseFloat(vv, 64)
if err == nil {
return vvv, nil
}
return 0, errConvFail
case []byte:
vvv, err := strconv.ParseFloat(string(vv), 64)
if err == nil {
return vvv, nil
}
return 0, errConvFail
case uint, uint8, uint16, uint32, uint64, uintptr:
return float64(Uint64(vv)), nil
case int, int8, int16, int32, int64:
return float64(Int(vv)), nil
case float32:
// use fmt to fix float32 -> float64 precision loss
// eg: cvt.Float64E(float32(8.31))
return strconv.ParseFloat(fmt.Sprintf("%f", vv), 64)
case float64:
return vv, nil
case json.Number:
return vv.Float64()
case time.Duration:
return float64(vv), nil
}
// indirect type
v, rv := Indirect(val)
switch vv := v.(type) {
case nil:
return 0, nil
case bool:
if vv {
return 1, nil
}
return 0, nil
case string:
return strconv.ParseFloat(vv, 64)
case []byte:
return strconv.ParseFloat(string(vv), 64)
case uint, uint8, uint16, uint32, uint64, uintptr:
return float64(rv.Uint()), nil
case int, int8, int16, int32, int64:
return float64(rv.Int()), nil
case float32:
// use fmt to fix float32 -> float64 precision loss
// eg: cvt.Float64E(float32(8.31))
return strconv.ParseFloat(fmt.Sprintf("%f", vv), 64)
case float64:
return vv, nil
}
return 0, errConvFail
}
// Float32 convert an interface to a float32 type, with default value
func Float32(v interface{}, def ...float32) float32 {
if v, err := Float32E(v); err == nil {
return v
}
if len(def) > 0 {
return def[0]
}
return 0
}
// Float32P convert and store in a new float32 value, and returns a pointer to it
func Float32P(v interface{}, def ...float32) *float32 {
i := Float32(v, def...)
return &i
}
// Float32E convert an interface to a float32 type
func Float32E(val interface{}) (float32, error) {
v, e := convFloat64E(val)
if e := catch("float32", val, e); e != nil {
return 0, e
}
if v > math.MaxFloat32 {
return 0, fmt.Errorf(formatOutOfLimitFloat, newErr(val, "float32"), float32(math.MaxFloat32))
}
return float32(v), nil
}