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 } func IntComma(i int) string { return BigComma(big.NewInt(int64(i))) }