105 lines
2.0 KiB
Go
105 lines
2.0 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
var NumberNames = map[int]string{
|
|
1: "тыс.",
|
|
2: "млн.",
|
|
3: "млрд.",
|
|
4: "трлн.",
|
|
5: "квадрлн.",
|
|
6: "квинтлн.",
|
|
7: "секстлн.",
|
|
8: "септлн.",
|
|
9: "октлн.",
|
|
10: "нонилн.",
|
|
11: "децилн.",
|
|
12: "ундецилн.",
|
|
13: "дуодецилн.",
|
|
}
|
|
|
|
func Short(n string) string {
|
|
d, err := decimal.NewFromString(n)
|
|
if err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
comma := DecimalComma(&d)
|
|
sp := strings.Split(comma, "'")
|
|
if len(sp) == 0 {
|
|
return ""
|
|
}
|
|
return fmt.Sprintf("(%s %s)", sp[0], NumberNames[len(sp)-1])
|
|
}
|
|
|
|
// order of magnitude (to a max order)
|
|
func oomm(n, b *big.Int, maxmag int) (float64, int) {
|
|
mag := 0
|
|
m := &big.Int{}
|
|
for n.Cmp(b) >= 0 {
|
|
n.DivMod(n, b, m)
|
|
mag++
|
|
if mag == maxmag && maxmag >= 0 {
|
|
break
|
|
}
|
|
}
|
|
return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
|
|
}
|
|
|
|
// total order of magnitude
|
|
// (same as above, but with no upper limit)
|
|
func oom(n, b *big.Int) (float64, int) {
|
|
mag := 0
|
|
m := &big.Int{}
|
|
for n.Cmp(b) >= 0 {
|
|
n.DivMod(n, b, m)
|
|
mag++
|
|
}
|
|
return float64(n.Int64()) + (float64(m.Int64()) / float64(b.Int64())), mag
|
|
}
|
|
|
|
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:], "'")
|
|
}
|
|
|
|
func DecimalComma(d *decimal.Decimal) string {
|
|
if d.IsInteger() {
|
|
return BigComma(d.BigInt())
|
|
}
|
|
fmt.Println(d.String())
|
|
exp := strings.Split(d.String(), ".")[1]
|
|
return BigComma(d.BigInt()) + "." + exp
|
|
}
|