comma.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package utils
  2. import (
  3. "bytes"
  4. "math"
  5. "math/big"
  6. "strconv"
  7. "strings"
  8. )
  9. // Comma 以逗号分隔开整数
  10. // e.g. Comma(834142) -> 834,142
  11. func Comma(v int64) string {
  12. sign := ""
  13. // Min int64 can't be negated to a usable value, so it has to be special cased.
  14. if v == math.MinInt64 {
  15. return "-9,223,372,036,854,775,808"
  16. }
  17. if v < 0 {
  18. sign = "-"
  19. v = 0 - v
  20. }
  21. parts := []string{"", "", "", "", "", "", ""}
  22. j := len(parts) - 1
  23. for v > 999 {
  24. parts[j] = strconv.FormatInt(v%1000, 10)
  25. switch len(parts[j]) {
  26. case 2:
  27. parts[j] = "0" + parts[j]
  28. case 1:
  29. parts[j] = "00" + parts[j]
  30. }
  31. v = v / 1000
  32. j--
  33. }
  34. parts[j] = strconv.Itoa(int(v))
  35. return sign + strings.Join(parts[j:], ",")
  36. }
  37. // Commaf 以逗号分隔开浮点数
  38. // e.g. Commaf(834142.32) -> 834,142.32
  39. func Commaf(v float64) string {
  40. buf := &bytes.Buffer{}
  41. if v < 0 {
  42. buf.Write([]byte{'-'})
  43. v = 0 - v
  44. }
  45. comma := []byte{','}
  46. parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".")
  47. pos := 0
  48. if len(parts[0])%3 != 0 {
  49. pos += len(parts[0]) % 3
  50. buf.WriteString(parts[0][:pos])
  51. buf.Write(comma)
  52. }
  53. for ; pos < len(parts[0]); pos += 3 {
  54. buf.WriteString(parts[0][pos : pos+3])
  55. buf.Write(comma)
  56. }
  57. buf.Truncate(buf.Len() - 1)
  58. if len(parts) > 1 {
  59. buf.Write([]byte{'.'})
  60. buf.WriteString(parts[1])
  61. }
  62. return buf.String()
  63. }
  64. // CommafWithDigits 以逗号分隔开浮点数, 且限制小数位
  65. // e.g. CommafWithDigits(834142.32, 1) -> 834,142.3
  66. func CommafWithDigits(f float64, decimals int) string {
  67. return stripTrailingDigits(Commaf(f), decimals)
  68. }
  69. // BigComma 以逗号分隔开超长整数
  70. func BigComma(b *big.Int) string {
  71. sign := ""
  72. if b.Sign() < 0 {
  73. sign = "-"
  74. b.Abs(b)
  75. }
  76. athousand := big.NewInt(1000)
  77. c := (&big.Int{}).Set(b)
  78. _, m := oom(c, athousand)
  79. parts := make([]string, m+1)
  80. j := len(parts) - 1
  81. mod := &big.Int{}
  82. for b.Cmp(athousand) >= 0 {
  83. b.DivMod(b, athousand, mod)
  84. parts[j] = strconv.FormatInt(mod.Int64(), 10)
  85. switch len(parts[j]) {
  86. case 2:
  87. parts[j] = "0" + parts[j]
  88. case 1:
  89. parts[j] = "00" + parts[j]
  90. }
  91. j--
  92. }
  93. parts[j] = strconv.Itoa(int(b.Int64()))
  94. return sign + strings.Join(parts[j:], ",")
  95. }
  96. func stripTrailingDigits(s string, digits int) string {
  97. if i := strings.Index(s, "."); i >= 0 {
  98. if digits <= 0 {
  99. return s[:i]
  100. }
  101. i++
  102. if i+digits >= len(s) {
  103. return s
  104. }
  105. return s[:i+digits]
  106. }
  107. return s
  108. }
  109. // total order of magnitude
  110. // (same as above, but with no upper limit)
  111. func oom(n, b *big.Int) (float64, int) {
  112. mag := 0
  113. m := &big.Int{}
  114. for n.Cmp(b) >= 0 {
  115. n.DivMod(n, b, m)
  116. mag++
  117. }
  118. return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
  119. }