frostfs-api-go/decimal/decimal.go

111 lines
2.8 KiB
Go

package decimal
import (
"math"
"strconv"
"strings"
)
// GASPrecision contains precision for NEO Gas token.
const GASPrecision = 8
// Zero is empty Decimal value.
var Zero = &Decimal{}
// New returns new Decimal (in satoshi).
func New(v int64) *Decimal {
return NewWithPrecision(v, GASPrecision)
}
// NewGAS returns new Decimal * 1e8 (in GAS).
func NewGAS(v int64) *Decimal {
v *= int64(math.Pow10(GASPrecision))
return NewWithPrecision(v, GASPrecision)
}
// NewWithPrecision returns new Decimal with custom precision.
func NewWithPrecision(v int64, p uint32) *Decimal {
return &Decimal{Value: v, Precision: p}
}
// ParseFloat return new Decimal parsed from float64 * 1e8 (in GAS).
func ParseFloat(v float64) *Decimal {
return new(Decimal).Parse(v, GASPrecision)
}
// ParseFloatWithPrecision returns new Decimal parsed from float64 * 1^p.
func ParseFloatWithPrecision(v float64, p int) *Decimal {
return new(Decimal).Parse(v, p)
}
// Copy returns copy of current Decimal.
func (m *Decimal) Copy() *Decimal { return &Decimal{Value: m.Value, Precision: m.Precision} }
// Parse returns parsed Decimal from float64 * 1^p.
func (m *Decimal) Parse(v float64, p int) *Decimal {
m.Value = int64(v * math.Pow10(p))
m.Precision = uint32(p)
return m
}
// String returns string representation of Decimal.
func (m Decimal) String() string {
buf := new(strings.Builder)
val := m.Value
dec := int64(math.Pow10(int(m.Precision)))
if val < 0 {
buf.WriteRune('-')
val = -val
}
str := strconv.FormatInt(val/dec, 10)
buf.WriteString(str)
val %= dec
if val > 0 {
buf.WriteRune('.')
str = strconv.FormatInt(val, 10)
for i := len(str); i < int(m.Precision); i++ {
buf.WriteRune('0')
}
buf.WriteString(strings.TrimRight(str, "0"))
}
return buf.String()
}
// Add returns d + m.
func (m Decimal) Add(d *Decimal) *Decimal {
precision := m.Precision
if precision < d.Precision {
precision = d.Precision
}
return &Decimal{
Value: m.Value + d.Value,
Precision: precision,
}
}
// Zero checks that Decimal is empty.
func (m Decimal) Zero() bool { return m.Value == 0 }
// Equal checks that current Decimal is equal to passed Decimal.
func (m Decimal) Equal(v *Decimal) bool { return m.Value == v.Value && m.Precision == v.Precision }
// GT checks that m > v.
func (m Decimal) GT(v *Decimal) bool { return m.Value > v.Value }
// GTE checks that m >= v.
func (m Decimal) GTE(v *Decimal) bool { return m.Value >= v.Value }
// LT checks that m < v.
func (m Decimal) LT(v *Decimal) bool { return m.Value < v.Value }
// LTE checks that m <= v.
func (m Decimal) LTE(v *Decimal) bool { return m.Value <= v.Value }
// Neg returns negative representation of current Decimal (m * -1).
func (m Decimal) Neg() *Decimal {
return &Decimal{
Value: m.Value * -1,
Precision: m.Precision,
}
}