Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
2.4 KiB
116 lines
2.4 KiB
package humanize |
|
|
|
import ( |
|
"bytes" |
|
"math" |
|
"math/big" |
|
"strconv" |
|
"strings" |
|
) |
|
|
|
// Comma produces a string form of the given number in base 10 with |
|
// commas after every three orders of magnitude. |
|
// |
|
// e.g. Comma(834142) -> 834,142 |
|
func Comma(v int64) string { |
|
sign := "" |
|
|
|
// Min int64 can't be negated to a usable value, so it has to be special cased. |
|
if v == math.MinInt64 { |
|
return "-9,223,372,036,854,775,808" |
|
} |
|
|
|
if v < 0 { |
|
sign = "-" |
|
v = 0 - v |
|
} |
|
|
|
parts := []string{"", "", "", "", "", "", ""} |
|
j := len(parts) - 1 |
|
|
|
for v > 999 { |
|
parts[j] = strconv.FormatInt(v%1000, 10) |
|
switch len(parts[j]) { |
|
case 2: |
|
parts[j] = "0" + parts[j] |
|
case 1: |
|
parts[j] = "00" + parts[j] |
|
} |
|
v = v / 1000 |
|
j-- |
|
} |
|
parts[j] = strconv.Itoa(int(v)) |
|
return sign + strings.Join(parts[j:], ",") |
|
} |
|
|
|
// Commaf produces a string form of the given number in base 10 with |
|
// commas after every three orders of magnitude. |
|
// |
|
// e.g. Commaf(834142.32) -> 834,142.32 |
|
func Commaf(v float64) string { |
|
buf := &bytes.Buffer{} |
|
if v < 0 { |
|
buf.Write([]byte{'-'}) |
|
v = 0 - v |
|
} |
|
|
|
comma := []byte{','} |
|
|
|
parts := strings.Split(strconv.FormatFloat(v, 'f', -1, 64), ".") |
|
pos := 0 |
|
if len(parts[0])%3 != 0 { |
|
pos += len(parts[0]) % 3 |
|
buf.WriteString(parts[0][:pos]) |
|
buf.Write(comma) |
|
} |
|
for ; pos < len(parts[0]); pos += 3 { |
|
buf.WriteString(parts[0][pos : pos+3]) |
|
buf.Write(comma) |
|
} |
|
buf.Truncate(buf.Len() - 1) |
|
|
|
if len(parts) > 1 { |
|
buf.Write([]byte{'.'}) |
|
buf.WriteString(parts[1]) |
|
} |
|
return buf.String() |
|
} |
|
|
|
// CommafWithDigits works like the Commaf but limits the resulting |
|
// string to the given number of decimal places. |
|
// |
|
// e.g. CommafWithDigits(834142.32, 1) -> 834,142.3 |
|
func CommafWithDigits(f float64, decimals int) string { |
|
return stripTrailingDigits(Commaf(f), decimals) |
|
} |
|
|
|
// BigComma produces a string form of the given big.Int in base 10 |
|
// with commas after every three orders of magnitude. |
|
func BigComma(b *big.Int) string { |
|
sign := "" |
|
if b.Sign() < 0 { |
|
sign = "-" |
|
b.Abs(b) |
|
} |
|
|
|
athousand := big.NewInt(1000) |
|
c := (&big.Int{}).Set(b) |
|
_, m := oom(c, athousand) |
|
parts := make([]string, m+1) |
|
j := len(parts) - 1 |
|
|
|
mod := &big.Int{} |
|
for b.Cmp(athousand) >= 0 { |
|
b.DivMod(b, athousand, mod) |
|
parts[j] = strconv.FormatInt(mod.Int64(), 10) |
|
switch len(parts[j]) { |
|
case 2: |
|
parts[j] = "0" + parts[j] |
|
case 1: |
|
parts[j] = "00" + parts[j] |
|
} |
|
j-- |
|
} |
|
parts[j] = strconv.Itoa(int(b.Int64())) |
|
return sign + strings.Join(parts[j:], ",") |
|
}
|
|
|