comma.go

  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 {
 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
 50func 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
 83func 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.
 89func 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}