Documentation
¶
Overview ¶
Package udecimal provides a high-performance, high-precision (up to 19 digits after the decimal point) decimal arithmetic library. It includes functions for parsing and performing arithmetic operations such as addition, subtraction, multiplication, and division on decimal numbers. The package is designed to handle decimal numbers with a high degree of precision and efficiency, making it suitable for high-traffic financial applications where both precision and performance are critical.
Maximum and default precision is 19 digits after the decimal point. The default precision can be changed globally to any value between 1 and 19 to suit your use case and make sure that the precision is consistent across the entire application. See SetDefaultPrecision for more details.
Codec ¶
The udecimal package supports various encoding and decoding mechanisms to facilitate easy integration with different data storage and transmission systems.
- Marshal/UnmarshalJSON
- Marshal/UnmarshalBinary: gob, protobuf
- SQL: The Decimal type implements the sql.Scanner interface, enabling seamless integration with SQL databases.
For more details, see the documentation for each method.
Index ¶
- Variables
- func SetDefaultPrecision(prec uint8)
- type Decimal
- func MustFromFloat64(f float64) Decimal
- func MustFromInt64(coef int64, prec uint8) Decimal
- func MustFromUint64(coef uint64, prec uint8) Decimal
- func MustParse(s string) Decimal
- func NewFromFloat64(f float64) (Decimal, error)
- func NewFromHiLo(neg bool, hi uint64, lo uint64, prec uint8) (Decimal, error)
- func NewFromInt64(coef int64, prec uint8) (Decimal, error)
- func NewFromUint64(coef uint64, prec uint8) (Decimal, error)
- func Parse(s string) (Decimal, error)
- func (d Decimal) Abs() Decimal
- func (d Decimal) Add(e Decimal) Decimal
- func (d Decimal) Add64(e uint64) Decimal
- func (d Decimal) Ceil() Decimal
- func (d Decimal) Cmp(e Decimal) int
- func (d Decimal) Div(e Decimal) (Decimal, error)
- func (d Decimal) Div64(v uint64) (Decimal, error)
- func (d Decimal) Equal(e Decimal) bool
- func (d Decimal) Floor() Decimal
- func (d Decimal) InexactFloat64() float64
- func (d Decimal) IsNeg() bool
- func (d Decimal) IsPos() bool
- func (d Decimal) IsZero() bool
- func (d Decimal) MarshalBinary() ([]byte, error)
- func (d Decimal) MarshalJSON() ([]byte, error)
- func (d Decimal) MarshalText() ([]byte, error)
- func (d Decimal) Mul(e Decimal) Decimal
- func (d Decimal) Mul64(v uint64) Decimal
- func (d Decimal) Neg() Decimal
- func (d Decimal) PowInt(e int) Decimal
- func (d Decimal) Prec() int
- func (d Decimal) RoundBank(prec uint8) Decimal
- func (d Decimal) RoundHAZ(prec uint8) Decimal
- func (d Decimal) RoundHTZ(prec uint8) Decimal
- func (d *Decimal) Scan(src any) error
- func (d Decimal) Sign() int
- func (d Decimal) Sqrt() (Decimal, error)
- func (d Decimal) String() string
- func (d Decimal) StringFixed(prec uint8) string
- func (d Decimal) Sub(e Decimal) Decimal
- func (d Decimal) Sub64(e uint64) Decimal
- func (d Decimal) Trunc(prec uint8) Decimal
- func (d *Decimal) UnmarshalBinary(data []byte) error
- func (d *Decimal) UnmarshalJSON(data []byte) error
- func (d *Decimal) UnmarshalText(data []byte) error
- func (d Decimal) Value() (driver.Value, error)
- type NullDecimal
Examples ¶
- Decimal.Abs
- Decimal.Add
- Decimal.Add64
- Decimal.Ceil
- Decimal.Cmp
- Decimal.Div
- Decimal.Div64
- Decimal.Equal
- Decimal.Floor
- Decimal.InexactFloat64
- Decimal.IsNeg
- Decimal.IsPos
- Decimal.IsZero
- Decimal.MarshalBinary
- Decimal.MarshalJSON
- Decimal.MarshalText
- Decimal.Mul
- Decimal.Mul64
- Decimal.Neg
- Decimal.PowInt
- Decimal.Prec
- Decimal.RoundBank
- Decimal.RoundHAZ
- Decimal.RoundHTZ
- Decimal.Scan
- Decimal.Sign
- Decimal.Sqrt
- Decimal.String
- Decimal.StringFixed
- Decimal.Sub
- Decimal.Sub64
- Decimal.Trunc
- Decimal.UnmarshalBinary
- Decimal.UnmarshalJSON
- Decimal.UnmarshalText
- Decimal.Value
- MustFromFloat64
- MustFromInt64
- MustFromUint64
- MustParse
- NewFromFloat64
- NewFromHiLo
- NewFromInt64
- NewFromUint64
- NullDecimal.Scan
- NullDecimal.Value
- Parse
- SetDefaultPrecision
Constants ¶
This section is empty.
Variables ¶
var ( // ErrPrecOutOfRange is returned when the decimal precision is greater than the default precision // default precision can be configured using SetDefaultPrecision, and its value is up to 19 ErrPrecOutOfRange = fmt.Errorf("precision out of range. Only support maximum %d digits after the decimal point", defaultPrec) // ErrEmptyString is returned when the input string is empty ErrEmptyString = fmt.Errorf("parse empty string") // ErrMaxStrLen is returned when the input string exceeds the maximum length // This limitation is set to prevent large string input which can cause performance issue // Maximum length is set to 200 ErrMaxStrLen = fmt.Errorf("string input exceeds maximum length %d", maxStrLen) // ErrInvalidFormat is returned when the input string is not in the correct format // It doesn't support scientific notation, such as 1e-2, 1.23e4, etc. ErrInvalidFormat = fmt.Errorf("invalid format") // ErrDivideByZero is returned when dividing by zero ErrDivideByZero = fmt.Errorf("can't divide by zero") // ErrSqrtNegative is returned when calculating square root of negative number ErrSqrtNegative = fmt.Errorf("can't calculate square root of negative number") // ErrInvalidBinaryData is returned when unmarshalling invalid binary data // The binary data should follow the format as described in MarshalBinary ErrInvalidBinaryData = fmt.Errorf("invalid binary data") )
var ( Zero = Decimal{} One = MustFromInt64(1, 0) )
Functions ¶
func SetDefaultPrecision ¶
func SetDefaultPrecision(prec uint8)
SetDefaultPrecision changes the default precision for decimal numbers in the package. Max precision is 19 and is also default.
This function is particularly useful when you want to have your precision of the deicmal smaller than 19 across the whole application. It should be called only once at the beginning of your application
Panics if the new precision is greater than 19 (maxPrec) or new precision is 0
Example ¶
SetDefaultPrecision(10)
defer SetDefaultPrecision(19)
a := MustParse("1.23")
b := MustParse("4.12475")
c, _ := a.Div(b)
fmt.Println(c)
Output: 0.2981998909
Types ¶
type Decimal ¶
type Decimal struct {
// contains filtered or unexported fields
}
Decimal represents a fixed-point decimal number. The number is represented as a struct with three fields: coef, neg, and prec.
- coef: the coefficient of the decimal number
- neg: true if the number is negative
- prec: the number of digits after the decimal point (0 to 19)
Decimal numbers are immutable and can be used in arithmetic operations such as addition, subtraction, multiplication, and division.
func MustFromFloat64 ¶
MustFromFloat64 similars to NewFromFloat64, but panics instead of returning error
Example ¶
fmt.Println(MustFromFloat64(1.234)) // cautious: result will lose some precision when converting to decimal fmt.Println(MustFromFloat64(123456789.1234567890123456789))
Output: 1.234 123456789.12345679
func MustFromInt64 ¶
MustFromInt64 similars to NewFromInt64, but panics instead of returning error
Example ¶
fmt.Println(MustFromInt64(123, 3)) fmt.Println(MustFromInt64(-12345, 2))
Output: 0.123 -123.45
func MustFromUint64 ¶
MustFromUint64 similars to NewFromUint64, but panics instead of returning error
Example ¶
fmt.Println(MustFromUint64(123, 3)) fmt.Println(MustFromUint64(12345, 2))
Output: 0.123 123.45
func MustParse ¶
MustParse similars to Parse, but pacnis instead of returning error.
Example ¶
fmt.Println(MustParse("1234567890123456789.1234567890123456789"))
fmt.Println(MustParse("-1234567890123456789.1234567890123456789"))
fmt.Println(MustParse("-0.00007890123456789"))
Output: 1234567890123456789.1234567890123456789 -1234567890123456789.1234567890123456789 -0.00007890123456789
func NewFromFloat64 ¶
NewFromFloat64 returns decimal from float64.
**NOTE**: you'll expect to lose some precision for this method due to FormatFloat. See: https://github.com/golang/go/issues/29491
This method is only suitable for small numbers with low precision. e.g. 1.0001, 0.0001, -123.456, -1000000.123456. You should avoid using this method if your input number has high precision.
Returns error when:
- f is NaN or Inf
- error when parsing float to string and then to decimal
Example ¶
fmt.Println(NewFromFloat64(1.234)) // cautious: result will lose some precision when converting to decimal fmt.Println(NewFromFloat64(123456789.1234567890123456789))
Output: 1.234 <nil> 123456789.12345679 <nil>
func NewFromHiLo ¶
NewFromHiLo returns Decimal from 128-bit unsigned integer (hi,lo)
Example ¶
fmt.Println(NewFromHiLo(false, 1, 1, 10)) fmt.Println(NewFromHiLo(true, 0, 123456, 4))
Output: 1844674407.3709551617 <nil> -12.3456 <nil>
func NewFromInt64 ¶
NewFromInt64 returns a decimal which equals to coef / 10^prec and coef is an int64. Trailing zeros wll be removed and the prec will also be adjusted
Example ¶
fmt.Println(NewFromInt64(123, 3)) fmt.Println(NewFromInt64(12345, 20))
Output: 0.123 <nil> 0 precision out of range. Only support maximum 19 digits after the decimal point
func NewFromUint64 ¶
NewFromUint64 returns a decimal which equals to coef / 10^prec and coef is an uint64 Trailing zeros wll be removed and the prec will also be adjusted
Example ¶
fmt.Println(NewFromUint64(123, 3)) fmt.Println(NewFromUint64(12345, 2)) fmt.Println(NewFromUint64(12345, 20))
Output: 0.123 <nil> 123.45 <nil> 0 precision out of range. Only support maximum 19 digits after the decimal point
func Parse ¶
Parse parses a number in string to Decimal. The string must be in the format of: [+-]d{1,19}[.d{1,19}]
Returns error if:
- empty/invalid string
- the number has more than 19 digits after the decimal point
Example ¶
fmt.Println(Parse("1234567890123456789.1234567890123456789"))
fmt.Println(Parse("-1234567890123456789.1234567890123456789"))
fmt.Println(Parse("-0.00007890123456789"))
// error cases
fmt.Println(Parse("0.12345678901234567890123"))
fmt.Println(Parse(""))
fmt.Println(Parse("1.123.123"))
Output: 1234567890123456789.1234567890123456789 <nil> -1234567890123456789.1234567890123456789 <nil> -0.00007890123456789 <nil> 0 precision out of range. Only support maximum 19 digits after the decimal point 0 parse empty string 0 invalid format: can't parse '1.123.123' to Decimal
func (Decimal) Abs ¶
Abs returns |d|
Example ¶
fmt.Println(MustParse("-123.45").Abs())
Output: 123.45
func (Decimal) Add ¶
Add returns d + e
Example ¶
a := MustParse("1.23")
b := MustParse("4.12475")
c := a.Add(b)
fmt.Println(c)
Output: 5.35475
func (Decimal) Add64 ¶
Add64 returns d + e where e is a uint64
Example ¶
a := MustParse("1.23")
c := a.Add64(4)
fmt.Println(c)
Output: 5.23
func (Decimal) Ceil ¶
Ceil returns the smallest integer value greater than or equal to d.
Example ¶
fmt.Println(MustParse("1.23").Ceil())
Output: 2
func (Decimal) Cmp ¶
Cmp compares two decimals d,e and returns:
-1 if d < e 0 if d == e +1 if d > e
Example ¶
fmt.Println(MustParse("1.23").Cmp(MustParse("4.12475")))
fmt.Println(MustParse("1.23").Cmp(MustParse("1.23")))
fmt.Println(MustParse("1.23").Cmp(MustParse("0.12475")))
Output: -1 0 1
func (Decimal) Div ¶
Div returns d / e. If the result has more than 19 fraction digits, it will be truncated to 19 digits.
Returns divide by zero error when e is zero
Example ¶
fmt.Println(MustParse("1.23").Div(MustParse("4.12475")))
fmt.Println(MustParse("1.23").Div(MustParse("0")))
Output: 0.2981998909024789381 <nil> 0 can't divide by zero
func (Decimal) Div64 ¶
Div64 returns d / e where e is a uint64. If the result has more than 19 fraction digits, it will be truncated to 19 digits.
Returns divide by zero error when e is zero
Example ¶
fmt.Println(MustParse("1.23").Div64(4))
fmt.Println(MustParse("1.23").Div64(0))
Output: 0.3075 <nil> 0 can't divide by zero
func (Decimal) Equal ¶ added in v1.2.0
Equal reports whether the two decimals d and e are equal.
Example ¶
fmt.Println(MustParse("1.123").Equal(MustParse("-1.123")))
fmt.Println(MustParse("1.123").Equal(MustParse("1.1230000")))
Output: false true
func (Decimal) Floor ¶
Floor returns the largest integer value less than or equal to d.
Example ¶
fmt.Println(MustParse("1.23").Floor())
fmt.Println(MustParse("-1.23").Floor())
Output: 1 -2
func (Decimal) InexactFloat64 ¶
InexactFloat64 returns the float64 representation of the decimal. The result may not be 100% accurate due to the limitation of float64 (less decimal precision).
Caution: this method will not return the exact number if the decimal is too large.
e.g. 123456789012345678901234567890123456789.9999999999999999999 -> 123456789012345680000000000000000000000
Example ¶
fmt.Println(MustParse("1.23").InexactFloat64())
fmt.Println(MustParse("123456789.123456789").InexactFloat64())
Output: 1.23 1.2345678912345679e+08
func (Decimal) IsNeg ¶
IsNeg returns
true if d < 0 false if d >= 0
Example ¶
fmt.Println(MustParse("1.23").IsNeg())
fmt.Println(MustParse("-1.23").IsNeg())
fmt.Println(MustParse("0").IsNeg())
Output: false true false
func (Decimal) IsPos ¶
IsPos returns
true if d > 0 false if d <= 0
Example ¶
fmt.Println(MustParse("1.23").IsPos())
fmt.Println(MustParse("-1.23").IsPos())
fmt.Println(MustParse("0").IsPos())
Output: true false false
func (Decimal) IsZero ¶
IsZero returns
true if d == 0 false if d != 0
Example ¶
fmt.Println(MustParse("1.23").IsZero())
fmt.Println(MustParse("0").IsZero())
Output: false true
func (Decimal) MarshalBinary ¶
MarshalBinary implements encoding.BinaryMarshaler interface with custom binary format.
Binary format: [overflow + neg] [prec] [total bytes] [coef] example 1: -1.2345 1st byte: 0b0001_0000 (overflow = true, neg = false) 2nd byte: 0b0000_0100 (prec = 4) 3rd byte: 0b0000_1101 (total bytes = 11) 4th-11th bytes: 0x0000_0000_0000_3039 (coef = 12345, only stores the coef.lo part) example 2: 1234567890123456789.1234567890123456789 1st byte: 0b0000_0000 (overflow = false, neg = false) 2nd byte: 0b0001_0011 (prec = 19) 3rd byte: 0b0001_0011 (total bytes = 19) 4th-11th bytes: 0x0949_b0f6_f002_3313 (coef.hi) 12th-19th bytes: 0xd3b5_05f9_b5f1_8115 (coef.lo)
Example ¶
fmt.Println(MustParse("1.23").MarshalBinary())
fmt.Println(MustParse("-1.2345").MarshalBinary())
fmt.Println(MustParse("1234567890123456789.1234567890123456789").MarshalBinary())
Output: [0 2 11 0 0 0 0 0 0 0 123] <nil> [1 4 11 0 0 0 0 0 0 48 57] <nil> [0 19 19 9 73 176 246 240 2 51 19 211 181 5 249 181 241 129 21] <nil>
func (Decimal) MarshalJSON ¶
MarshalJSON implements the json.Marshaler interface.
Example ¶
a, _ := MustParse("1.23").MarshalJSON()
b, _ := MustParse("-1.2345").MarshalJSON()
c, _ := MustParse("1234567890123456789.1234567890123456789").MarshalJSON()
fmt.Println(string(a))
fmt.Println(string(b))
fmt.Println(string(c))
Output: "1.23" "-1.2345" "1234567890123456789.1234567890123456789"
func (Decimal) MarshalText ¶ added in v1.2.0
MarshalText implements the encoding.TextMarshaler interface.
Example ¶
a, _ := MustParse("1.23").MarshalText()
b, _ := MustParse("-1.2345").MarshalText()
c, _ := MustParse("1234567890123456789.1234567890123456789").MarshalText()
fmt.Println(string(a))
fmt.Println(string(b))
fmt.Println(string(c))
Output: 1.23 -1.2345 1234567890123456789.1234567890123456789
func (Decimal) Mul ¶
Mul returns d * e. The result will have at most defaultPrec digits after the decimal point.
Example ¶
a := MustParse("1.23")
b := MustParse("4.12475")
c := a.Mul(b)
fmt.Println(c)
Output: 5.0734425
func (Decimal) Mul64 ¶
Mul64 returns d * e where e is a uint64. The result will have at most defaultPrec digits after the decimal point.
Example ¶
a := MustParse("1.23")
c := a.Mul64(4)
fmt.Println(c)
Output: 4.92
func (Decimal) Neg ¶
Neg returns -d
Example ¶
fmt.Println(MustParse("1.23").Neg())
fmt.Println(MustParse("-1.23").Neg())
Output: -1.23 1.23
func (Decimal) PowInt ¶
PowInt returns d^e where e is an integer.
Examples:
PowInt(2.5, 2) = 6.25 PowInt(2.5, -2) = 0.16
Example ¶
fmt.Println(MustParse("1.23").PowInt(2))
fmt.Println(MustParse("1.23").PowInt(0))
fmt.Println(MustParse("1.23").PowInt(-2))
Output: 1.5129 1 0.6609822195782933439
func (Decimal) Prec ¶
Prec returns decimal precision
Example ¶
fmt.Println(MustParse("1.23").Prec())
Output: 2
func (Decimal) RoundBank ¶
RoundBank uses half up to even (banker's rounding) to round the decimal to the specified prec.
Examples:
RoundBank(1.12345, 4) = 1.1234 RoundBank(1.12335, 4) = 1.1234 RoundBank(1.5, 0) = 2 RoundBank(-1.5, 0) = -2
Example ¶
fmt.Println(MustParse("1.12345").RoundBank(4))
fmt.Println(MustParse("1.12335").RoundBank(4))
fmt.Println(MustParse("1.5").RoundBank(0))
fmt.Println(MustParse("-1.5").RoundBank(0))
Output: 1.1234 1.1234 2 -2
func (Decimal) RoundHAZ ¶
RoundHAZ rounds the decimal to the specified prec using HALF AWAY FROM ZERO method (https://en.wikipedia.org/wiki/Rounding#Rounding_half_away_from_zero).
Examples:
Round(1.12345, 4) = 1.1235 Round(1.12335, 4) = 1.1234 Round(1.5, 0) = 2 Round(-1.5, 0) = -2
Example ¶
fmt.Println(MustParse("1.12345").RoundHAZ(4))
fmt.Println(MustParse("1.12335").RoundHAZ(4))
fmt.Println(MustParse("1.5").RoundHAZ(0))
fmt.Println(MustParse("-1.5").RoundHAZ(0))
Output: 1.1235 1.1234 2 -2
func (Decimal) RoundHTZ ¶
RoundHTZ rounds the decimal to the specified prec using HALF TOWARD ZERO method (https://en.wikipedia.org/wiki/Rounding#Rounding_half_toward_zero).
Examples:
Round(1.12345, 4) = 1.1234 Round(1.12335, 4) = 1.1233 Round(1.5, 0) = 1 Round(-1.5, 0) = -1
Example ¶
fmt.Println(MustParse("1.12345").RoundHTZ(4))
fmt.Println(MustParse("1.12335").RoundHTZ(4))
fmt.Println(MustParse("1.5").RoundHTZ(0))
fmt.Println(MustParse("-1.5").RoundHTZ(0))
Output: 1.1234 1.1233 1 -1
func (*Decimal) Scan ¶
Scan implements sql.Scanner interface.
Example ¶
var a Decimal
_ = a.Scan("1.23")
fmt.Println(a)
Output: 1.23
func (Decimal) Sign ¶
Sign returns:
-1 if d < 0 0 if d == 0 +1 if d > 0
Example ¶
fmt.Println(MustParse("1.23").Sign())
fmt.Println(MustParse("-1.23").Sign())
fmt.Println(MustParse("0").Sign())
Output: 1 -1 0
func (Decimal) Sqrt ¶
Sqrt returns the square root of d using Newton-Raphson method. The result will have at most defaultPrec digits after the decimal point. Returns error if d < 0
Examples:
Sqrt(4) = 2 Sqrt(2) = 1.4142135623730950488
Example ¶
fmt.Println(MustParse("1.21").Sqrt())
fmt.Println(MustParse("0").Sqrt())
fmt.Println(MustParse("-1.21").Sqrt())
Output: 1.1 <nil> 0 <nil> 0 can't calculate square root of negative number
func (Decimal) String ¶
String returns the string representation of the decimal. Trailing zeros will be removed.
Example ¶
fmt.Println(MustParse("1.23").String())
fmt.Println(MustParse("-1.230000").String())
Output: 1.23 -1.23
func (Decimal) StringFixed ¶
StringFixed returns the string representation of the decimal with fixed prec. Trailing zeros will not be removed.
Special case: if the decimal is zero, it will return "0" regardless of the prec.
Example ¶
fmt.Println(MustParse("1.23").StringFixed(4))
fmt.Println(MustParse("-1.230000").StringFixed(5))
Output: 1.2300 -1.23000
func (Decimal) Sub ¶
Sub returns d - e
Example ¶
a := MustParse("1.23")
b := MustParse("4.12475")
c := a.Sub(b)
fmt.Println(c)
Output: -2.89475
func (Decimal) Sub64 ¶
Sub64 returns d - e where e is a uint64
Example ¶
a := MustParse("1.23")
c := a.Sub64(4)
fmt.Println(c)
Output: -2.77
func (Decimal) Trunc ¶
Trunc returns d after truncating the decimal to the specified prec.
Examples:
Trunc(1.12345, 4) = 1.1234 Trunc(1.12335, 4) = 1.1233
Example ¶
fmt.Println(MustParse("1.23").Trunc(1))
fmt.Println(MustParse("-1.23").Trunc(5))
Output: 1.2 -1.23
func (*Decimal) UnmarshalBinary ¶
Example ¶
var a Decimal
_ = a.UnmarshalBinary([]byte{0, 2, 11, 0, 0, 0, 0, 0, 0, 0, 123})
fmt.Println(a)
Output: 1.23
func (*Decimal) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface.
Example ¶
var a Decimal
_ = a.UnmarshalJSON([]byte("1.23"))
fmt.Println(a)
Output: 1.23
func (*Decimal) UnmarshalText ¶ added in v1.2.0
UnmarshalText implements the encoding.TextUnmarshaler interface.
Example ¶
var a Decimal
_ = a.UnmarshalText([]byte("1.23"))
fmt.Println(a)
Output: 1.23
type NullDecimal ¶
NullDecimal is a nullable Decimal.
func (*NullDecimal) Scan ¶
func (d *NullDecimal) Scan(src any) error
Scan implements sql.Scanner interface.
Example ¶
var a, b NullDecimal
_ = a.Scan("1.23")
_ = b.Scan(nil)
fmt.Println(a)
fmt.Println(b)
Output: {1.23 true} {0 false}
func (NullDecimal) Value ¶
func (d NullDecimal) Value() (driver.Value, error)
Value implements the driver.Valuer interface.
Example ¶
fmt.Println(NullDecimal{Decimal: MustParse("1.2345"), Valid: true}.Value())
fmt.Println(NullDecimal{}.Value())
Output: 1.2345 <nil> <nil> <nil>