1 package humanize
2
3 import (
4 "errors"
5 "math"
6 "regexp"
7 "strconv"
8 )
9
10 var siPrefixTable = map[float64]string{
11 -30: "q",
12 -27: "r",
13 -24: "y",
14 -21: "z",
15 -18: "a",
16 -15: "f",
17 -12: "p",
18 -9: "n",
19 -6: "ยต",
20 -3: "m",
21 0: "",
22 3: "k",
23 6: "M",
24 9: "G",
25 12: "T",
26 15: "P",
27 18: "E",
28 21: "Z",
29 24: "Y",
30 27: "R",
31 30: "Q",
32 }
33
34 var revSIPrefixTable = revfmap(siPrefixTable)
35
36
37 func revfmap(in map[float64]string) map[string]float64 {
38 rv := map[string]float64{}
39 for k, v := range in {
40 rv[v] = math.Pow(10, k)
41 }
42 return rv
43 }
44
45 var riParseRegex *regexp.Regexp
46
47 func init() {
48 ri := `^([\-0-9.]+)\s?([`
49 for _, v := range siPrefixTable {
50 ri += v
51 }
52 ri += `]?)(.*)`
53
54 riParseRegex = regexp.MustCompile(ri)
55 }
56
57
58
59
60
61
62
63
64 func ComputeSI(input float64) (float64, string) {
65 if input == 0 {
66 return 0, ""
67 }
68 mag := math.Abs(input)
69 exponent := math.Floor(logn(mag, 10))
70 exponent = math.Floor(exponent/3) * 3
71
72 value := mag / math.Pow(10, exponent)
73
74
75
76 if value == 1000.0 {
77 exponent += 3
78 value = mag / math.Pow(10, exponent)
79 }
80
81 value = math.Copysign(value, input)
82
83 prefix := siPrefixTable[exponent]
84 return value, prefix
85 }
86
87
88
89
90
91
92
93
94
95 func SI(input float64, unit string) string {
96 value, prefix := ComputeSI(input)
97 return Ftoa(value) + " " + prefix + unit
98 }
99
100
101
102
103
104
105 func SIWithDigits(input float64, decimals int, unit string) string {
106 value, prefix := ComputeSI(input)
107 return FtoaWithDigits(value, decimals) + " " + prefix + unit
108 }
109
110 var errInvalid = errors.New("invalid input")
111
112
113
114
115
116
117 func ParseSI(input string) (float64, string, error) {
118 found := riParseRegex.FindStringSubmatch(input)
119 if len(found) != 4 {
120 return 0, "", errInvalid
121 }
122 mag := revSIPrefixTable[found[2]]
123 unit := found[3]
124
125 base, err := strconv.ParseFloat(found[1], 64)
126 return base * mag, unit, err
127 }
128
View as plain text