comma.go (2476B)
1 package humanize 2 3 import ( 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 15 func Comma(v int64) string { 16 sign := "" 17 18 // Min int64 can't be negated to a usable value, so it has to be special cased. 19 if v == math.MinInt64 { 20 return "-9,223,372,036,854,775,808" 21 } 22 23 if v < 0 { 24 sign = "-" 25 v = 0 - v 26 } 27 28 parts := []string{"", "", "", "", "", "", ""} 29 j := len(parts) - 1 30 31 for v > 999 { 32 parts[j] = strconv.FormatInt(v%1000, 10) 33 switch len(parts[j]) { 34 case 2: 35 parts[j] = "0" + parts[j] 36 case 1: 37 parts[j] = "00" + parts[j] 38 } 39 v = v / 1000 40 j-- 41 } 42 parts[j] = strconv.Itoa(int(v)) 43 return 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 50 func Commaf(v float64) string { 51 buf := &bytes.Buffer{} 52 if v < 0 { 53 buf.Write([]byte{'-'}) 54 v = 0 - v 55 } 56 57 comma := []byte{','} 58 59 parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".") 60 pos := 0 61 if len(parts[0])%3 != 0 { 62 pos += len(parts[0]) % 3 63 buf.WriteString(parts[0][:pos]) 64 buf.Write(comma) 65 } 66 for ; pos < len(parts[0]); pos += 3 { 67 buf.WriteString(parts[0][pos : pos+3]) 68 buf.Write(comma) 69 } 70 buf.Truncate(buf.Len() - 1) 71 72 if len(parts) > 1 { 73 buf.Write([]byte{'.'}) 74 buf.WriteString(parts[1]) 75 } 76 return 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 83 func CommafWithDigits(f float64, decimals int) string { 84 return 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. 89 func BigComma(b *big.Int) string { 90 sign := "" 91 if b.Sign() < 0 { 92 sign = "-" 93 b.Abs(b) 94 } 95 96 athousand := big.NewInt(1000) 97 c := (&big.Int{}).Set(b) 98 _, m := oom(c, athousand) 99 parts := make([]string, m+1) 100 j := len(parts) - 1 101 102 mod := &big.Int{} 103 for b.Cmp(athousand) >= 0 { 104 b.DivMod(b, athousand, mod) 105 parts[j] = strconv.FormatInt(mod.Int64(), 10) 106 switch len(parts[j]) { 107 case 2: 108 parts[j] = "0" + parts[j] 109 case 1: 110 parts[j] = "00" + parts[j] 111 } 112 j-- 113 } 114 parts[j] = strconv.Itoa(int(b.Int64())) 115 return sign + strings.Join(parts[j:], ",") 116 }