cubefs
116 строк · 2.4 Кб
1package humanize
2
3import (
4"bytes"
5"math"
6"math/big"
7"strconv"
8"strings"
9)
10
11// Comma produces a string form of the given number in base 10 with
12// commas after every three orders of magnitude.
13//
14// e.g. Comma(834142) -> 834,142
15func Comma(v int64) string {
16sign := ""
17
18// Min int64 can't be negated to a usable value, so it has to be special cased.
19if v == math.MinInt64 {
20return "-9,223,372,036,854,775,808"
21}
22
23if v < 0 {
24sign = "-"
25v = 0 - v
26}
27
28parts := []string{"", "", "", "", "", "", ""}
29j := len(parts) - 1
30
31for v > 999 {
32parts[j] = strconv.FormatInt(v%1000, 10)
33switch len(parts[j]) {
34case 2:
35parts[j] = "0" + parts[j]
36case 1:
37parts[j] = "00" + parts[j]
38}
39v = v / 1000
40j--
41}
42parts[j] = strconv.Itoa(int(v))
43return sign + strings.Join(parts[j:], ",")
44}
45
46// Commaf produces a string form of the given number in base 10 with
47// commas after every three orders of magnitude.
48//
49// e.g. Commaf(834142.32) -> 834,142.32
50func Commaf(v float64) string {
51buf := &bytes.Buffer{}
52if v < 0 {
53buf.Write([]byte{'-'})
54v = 0 - v
55}
56
57comma := []byte{','}
58
59parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
60pos := 0
61if len(parts[0])%3 != 0 {
62pos += len(parts[0]) % 3
63buf.WriteString(parts[0][:pos])
64buf.Write(comma)
65}
66for ; pos < len(parts[0]); pos += 3 {
67buf.WriteString(parts[0][pos : pos+3])
68buf.Write(comma)
69}
70buf.Truncate(buf.Len() - 1)
71
72if len(parts) > 1 {
73buf.Write([]byte{'.'})
74buf.WriteString(parts[1])
75}
76return buf.String()
77}
78
79// CommafWithDigits works like the Commaf but limits the resulting
80// string to the given number of decimal places.
81//
82// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
83func CommafWithDigits(f float64, decimals int) string {
84return stripTrailingDigits(Commaf(f), decimals)
85}
86
87// BigComma produces a string form of the given big.Int in base 10
88// with commas after every three orders of magnitude.
89func BigComma(b *big.Int) string {
90sign := ""
91if b.Sign() < 0 {
92sign = "-"
93b.Abs(b)
94}
95
96athousand := big.NewInt(1000)
97c := (&big.Int{}).Set(b)
98_, m := oom(c, athousand)
99parts := make([]string, m+1)
100j := len(parts) - 1
101
102mod := &big.Int{}
103for b.Cmp(athousand) >= 0 {
104b.DivMod(b, athousand, mod)
105parts[j] = strconv.FormatInt(mod.Int64(), 10)
106switch len(parts[j]) {
107case 2:
108parts[j] = "0" + parts[j]
109case 1:
110parts[j] = "00" + parts[j]
111}
112j--
113}
114parts[j] = strconv.Itoa(int(b.Int64()))
115return sign + strings.Join(parts[j:], ",")
116}
117