comma.go 2.4 KB

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