Documentation
¶
Overview ¶
Package decimal implements immutable decimal floating-point numbers.
This packages is designed specifically for use in transactional financial systems. The amounts involved in financial transactions typically do not exceed 99,999,999,999,999,999.99, so uint64 is used to store decimal coefficients, which reduces heap allocations, lowers memory consumption, and improves performance.
Features ¶
- Decimal values are immutable, making them safe to use in multiple goroutines.
- Supports simple, straightforward string representation without scientific or engineering notation.
- Uses half-even rounding for arithmetic operations, with the ability to panic if significant digits are lost.
- Does not support special values such as NaN, Infinity, or signed zeros, ensuring that arithmetic operations always produce well-defined results.
Representation ¶
A Decimal value is represented as a struct with three parameters:
- Sign: a boolean indicating whether the decimal is negative.
- Coefficient: an uint64 value.
- Scale: an integer indicating the position of the floating decimal point.
The scale field determines the position of the decimal point in the coefficient. For example, a decimal value with a scale of 2 represents a value that has two digits after the decimal point. The coefficient field is the integer value of the decimal without the decimal point. For example, a decimal with a coefficient of 12345 and a scale of 2 represents the value 123.45. Such approach allows for multiple representations of the same numerical value. For example, 1, 1.0, and 1.00 all represent the same value, but they have different scales and coefficients.
One important aspect of the Decimal is that it does not support special values such as NaN, Infinity, or signed zeros. This makes the representation simpler and more efficient, and it ensures that arithmetic operations always produce well-defined results.
Supported Ranges ¶
The range of a decimal value depends on its scale and the size of its coefficient. Since the coefficient is stored as an uint64, a Decimal can have a maximum of 19 digits. Additionally, the range of the Decimal depends on its scale, which determines the number of decimal places. Here are some examples of ranges supported for frequently used scales:
| Scale | Minimum | Maximum | Example | | ----- | ------------------------------------ | ----------------------------------- | -------------------------- | | 0 | -9,999,999,999,999,999,999 | 9,999,999,999,999,999,999 | Japanese Yen | | 2 | -99,999,999,999,999,999.99 | 99,999,999,999,999,999.99 | US Dollar | | 3 | -9,999,999,999,999,999.999 | 9,999,999,999,999,999.999 | Omani Rial | | 8 | -99,999,999,999.99999999 | 99,999,999,999.99999999 | Bitcoin | | 9 | -9,999,999,999.999999999 | 9,999,999,999.999999999 | US Dollar (high-precision) | | | | | or Etherium |
Operations ¶
Arithmetic operations in this package are based on General Decimal Arithmetic and generally involve two steps:
The operation is first performed using only uint64 variables. If no overflow occurs, the result is returned. If an overflow occurs, the operation proceeds to step 2.
The operation is performed again using big.Int variables. The result is rounded to fit into 19 digits. If no significant digits are lost during rounding, the result is returned. If significant digits are lost, a panic is raised.
The purpose of the first step is to optimize the performance of arithmetic operations and reduce memory consumption. Since the coefficient is stored as an uint64, arithmetic operations using only uint64 variables can be performed quickly and efficiently. It is expected that most of the arithmetic operations will be successfully completed during the first step.
The following rules are used to determine the significance of digits:
- Decimal.Add, Decimal.Sub, Decimal.Mul, Decimal.FMA, Decimal.Pow, Decimal.Quo, Decimal.QuoRem: All digits in the integer part are significant, while the digits in the fractional part are insignificant.
- Decimal.AddExact, Decimal.SubExact, Decimal.MulExact, Decimal.FMAExact, Decimal.QuoExact: All digits in the integer part are significant. The significance of digits in the fractional part is determined by the scale argument, which is typically equal to the scale of the currency.
Rounding ¶
To fit the results of arithmetic operations into 19 digits, the package uses half-to-even rounding, which ensures that rounding errors are evenly distributed between rounding up and rounding down.
In addition to implicit half-to-even rounding, the Decimal package provides several methods for explicit rounding:
- Decimal.Ceil: rounds towards positive infinity.
- Decimal.Floor: rounds towards negative infinity.
- Decimal.Trunc: rounds towards zero.
- Decimal.Round: uses half-to-even rounding.
Errors ¶
Arithmetic operations panic in the following cases:
Out-of-range scale. This error is expected to be very rare as the scale usually comes from a global constant or an established standard, such as ISO 4217. If this error occurs, it suggests a significant bug.
Coefficient overflow. This error occurs when significant digits are lost during rounding to fit 19 digits. This typically happens when dealing with large numbers or when you requested large number of digits after the decimal point to be considered signigicant. Refer to the supported ranges section, if your application needs to handle numbers that are close to the minimum or maximum values, this package may not be suitable. Consider using packages that store coefficients using big.Int type, such as ShopSpring Decimal or CockroachDB Decimal.
Division by zero. This package follows the convention of the standard library and will panic in case of division by zero.
Example (LeibnizPi) ¶
This example calculates an approximate value of pi using the Leibniz formula for pi. The Leibniz formula is an infinite series that converges to pi/4, and is given by the equation: 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + ... = pi/4. This example computes the series up to the 5000th term using decimal arithmetic and returns the approximate value of pi.
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { pi := decimal.New(0, 0) dividend := decimal.New(4, 0) divisor := decimal.New(1, 0) sign := decimal.New(1, 0) step := decimal.New(2, 0) for i := 0; i < 5000; i++ { pi = pi.Add(dividend.Quo(divisor).Mul(sign)) divisor = divisor.Add(step) sign = sign.Neg() } fmt.Println(pi) }
Output: 3.141392653591793247
Example (PolishNotation) ¶
This example implements a simple calculator that evaluates mathematical expressions written in postfix (or reverse Polish) notation. The calculator can handle basic arithmetic operations such as addition, subtraction, multiplication, and division.
package main import ( "fmt" "github.com/govalues/decimal" "strings" ) func evaluate(input string) (decimal.Decimal, error) { tokens := strings.Fields(input) stack := make([]decimal.Decimal, 0, len(tokens)) for i := len(tokens) - 1; i >= 0; i-- { token := tokens[i] switch token { default: d, err := decimal.Parse(token) if err != nil { return decimal.Decimal{}, fmt.Errorf("invalid decimal: %s", token) } stack = append(stack, d) case "+", "-", "*", "/": if len(stack) < 2 { return decimal.Decimal{}, fmt.Errorf("invalid input") } d := stack[len(stack)-1] e := stack[len(stack)-2] stack = stack[:len(stack)-2] var f decimal.Decimal switch token { case "+": f = d.Add(e) case "-": f = d.Sub(e) case "*": f = d.Mul(e) case "/": f = d.Quo(e) } stack = append(stack, f) } } if len(stack) != 1 { return decimal.Decimal{}, fmt.Errorf("invalid input") } return stack[0], nil } func main() { d, err := evaluate("* 10 + 1.2 3.4") if err != nil { panic(err) } fmt.Println(d) }
Output: 46.0
Index ¶
- Constants
- type Decimal
- func (d Decimal) Abs() Decimal
- func (d Decimal) Add(e Decimal) Decimal
- func (d Decimal) AddExact(e Decimal, scale int) Decimal
- func (d Decimal) Ceil(scale int) Decimal
- func (d Decimal) Cmp(e Decimal) int
- func (d Decimal) CmpTotal(e Decimal) int
- func (d Decimal) Coef() uint64
- func (d Decimal) CopySign(e Decimal) Decimal
- func (d Decimal) FMA(e, f Decimal) Decimal
- func (d Decimal) FMAExact(e, f Decimal, scale int) Decimal
- func (d Decimal) Floor(scale int) Decimal
- func (d Decimal) Format(state fmt.State, verb rune)
- func (d Decimal) IsInt() bool
- func (d Decimal) IsNeg() bool
- func (d Decimal) IsOne() bool
- func (d Decimal) IsPos() bool
- func (d Decimal) IsZero() bool
- func (d Decimal) LessThanOne() bool
- func (d Decimal) MarshalText() ([]byte, error)
- func (d Decimal) Max(e Decimal) Decimal
- func (d Decimal) Min(e Decimal) Decimal
- func (d Decimal) MinScale() int
- func (d Decimal) Mul(e Decimal) Decimal
- func (d Decimal) MulExact(e Decimal, scale int) Decimal
- func (d Decimal) Neg() Decimal
- func (d Decimal) Pow(exp int) Decimal
- func (d Decimal) Prec() int
- func (d Decimal) Quantize(e Decimal) Decimal
- func (d Decimal) Quo(e Decimal) Decimal
- func (d Decimal) QuoExact(e Decimal, scale int) Decimal
- func (d Decimal) QuoRem(e Decimal) (Decimal, Decimal)
- func (d Decimal) Reduce() Decimal
- func (d Decimal) Round(scale int) Decimal
- func (d Decimal) Scale() int
- func (d Decimal) Sign() int
- func (d Decimal) String() string
- func (d Decimal) Sub(e Decimal) Decimal
- func (d Decimal) SubExact(e Decimal, scale int) Decimal
- func (d Decimal) Trunc(scale int) Decimal
- func (d Decimal) ULP() Decimal
- func (d *Decimal) UnmarshalText(text []byte) error
- func (d Decimal) WithScale(scale int) Decimal
Examples ¶
- Package (LeibnizPi)
- Package (PolishNotation)
- Decimal.Abs
- Decimal.Add
- Decimal.AddExact
- Decimal.Ceil
- Decimal.Cmp
- Decimal.CmpTotal
- Decimal.Coef
- Decimal.CopySign
- Decimal.FMA
- Decimal.FMAExact
- Decimal.Floor
- Decimal.Format
- Decimal.IsInt
- Decimal.IsNeg
- Decimal.IsOne
- Decimal.IsPos
- Decimal.IsZero
- Decimal.LessThanOne
- Decimal.MarshalText
- Decimal.Max
- Decimal.Min
- Decimal.MinScale
- Decimal.Mul
- Decimal.MulExact
- Decimal.Neg
- Decimal.Pow
- Decimal.Prec
- Decimal.Quantize
- Decimal.Quo
- Decimal.QuoExact
- Decimal.QuoRem
- Decimal.Reduce
- Decimal.Round
- Decimal.Scale
- Decimal.Sign
- Decimal.String
- Decimal.Sub
- Decimal.SubExact
- Decimal.Trunc
- Decimal.ULP
- Decimal.UnmarshalText
- Decimal.WithScale
- MustParse
- New
- Parse
- ParseExact
Constants ¶
const ( MaxPrec = 19 // maximum length of the coefficient in decimal digits MaxScale = MaxPrec // maximum number of digits after the decimal point )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Decimal ¶
type Decimal struct {
// contains filtered or unexported fields
}
Decimal type is a representation of a finite floating-point decimal. It is designed to be safe for concurrent use by multiple goroutines. The zero value for Decimal represents the value 0.
func MustParse ¶
MustParse is like Parse but panics if the string cannot be parsed. It simplifies safe initialization of global variables holding decimals.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-1.230") fmt.Println(d) }
Output: -1.230
func New ¶
New returns a decimal equal to coef / 10^scale. New panics if scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.New(-1230, 3) fmt.Println(d) }
Output: -1.230
func Parse ¶
Parse converts a string to a (possibly rounded) decimal. The input string must be in one of the following formats:
1.234 -1234 +0.000001234 1.83e5 0.22e-9
The formal EBNF grammar for the supported format is as follows:
sign ::= '+' | '-' digits ::= { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' } significand ::= digits '.' digits | '.' digits | digits '.' | digits exponent ::= ('e' | 'E') [sign] digits numeric-string ::= [sign] significand [exponent]
Parse removes leading zeros from the integer part of the input string, but tries to maintain trailing zeros in the fractional part to preserve scale.
Parse returns error:
- if string does not represent a valid decimal number.
- if integer part of the result has more than MaxPrec digits.
- if exponent is less than -2 * MaxScale or greater than 2 * MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d, err := decimal.Parse("-1.230") if err != nil { panic(err) } fmt.Println(d) }
Output: -1.230
func ParseExact ¶
ParseExact is similar to Parse, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will return error. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d, err := decimal.ParseExact("-1.2", 5) if err != nil { panic(err) } fmt.Println(d) }
Output: -1.20000
func (Decimal) Abs ¶
Abs returns absolute value of d.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") fmt.Println(d.Abs()) }
Output: 15.67
func (Decimal) Add ¶
Add returns (possibly rounded) sum of d and e.
Add panics if the integer part of the sum has more than MaxPrec digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.6") e := decimal.MustParse("8") fmt.Println(d.Add(e)) }
Output: 23.6
func (Decimal) AddExact ¶
AddExact is similar to Decimal.Add, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will panic. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.6") e := decimal.MustParse("8") fmt.Println(d.AddExact(e, 2)) }
Output: 23.60
func (Decimal) Ceil ¶
Ceil returns d that is rounded up to the specified number of digits after the decimal point. If the scale of d is less than the specified scale, the result will be zero-padded to the right. Also see method Decimal.Floor.
Ceil panics if:
- the integer part of the result has more than (MaxPrec - scale) digits;
- the scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") fmt.Println(d.Ceil(6)) fmt.Println(d.Ceil(5)) fmt.Println(d.Ceil(4)) fmt.Println(d.Ceil(3)) fmt.Println(d.Ceil(2)) fmt.Println(d.Ceil(1)) fmt.Println(d.Ceil(0)) }
Output: 15.679000 15.67900 15.6790 15.679 15.68 15.7 16
func (Decimal) Cmp ¶
Cmp compares d and e numerically and returns:
-1 if d < e 0 if d == e +1 if d > e
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23") e := decimal.MustParse("-15.67") fmt.Println(d.Cmp(e)) fmt.Println(d.Cmp(d)) fmt.Println(e.Cmp(d)) }
Output: 1 0 -1
func (Decimal) CmpTotal ¶
CmpTotal compares representation of d and e and returns:
-1 if d < e -1 if d == e && d.scale > e.scale 0 if d == e && d.scale == e.scale +1 if d == e && d.scale < e.scale +1 if d > e
Also see method Decimal.Cmp.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("2.0") e := decimal.MustParse("2.00") fmt.Println(d.CmpTotal(e)) fmt.Println(d.CmpTotal(d)) fmt.Println(e.CmpTotal(d)) }
Output: 1 0 -1
func (Decimal) Coef ¶
Coef returns the coefficient of the decimal. Also see method Decimal.Prec.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-123") e := decimal.MustParse("5.7") f := decimal.MustParse("0.4") fmt.Println(d.Coef()) fmt.Println(e.Coef()) fmt.Println(f.Coef()) }
Output: 123 57 4
func (Decimal) CopySign ¶ added in v0.0.7
CopySign returns d with the same sign as e. If e is zero, sign of d remains unchanged.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23.00") e := decimal.MustParse("-15.67") fmt.Println(d.CopySign(e)) fmt.Println(e.CopySign(d)) }
Output: -23.00 15.67
func (Decimal) FMA ¶ added in v0.0.3
FMA returns (possibly rounded) fused multiply-addition of d, e, and f. It computes d * e + f without any intermeddiate rounding. This method is useful for improving the accuracy and performance of algorithms that involve the accumulation of products, such as daily interest accrual.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("5.7") e := decimal.MustParse("3") f := decimal.MustParse("2.8") fmt.Println(d.FMA(e, f)) }
Output: 19.9
func (Decimal) FMAExact ¶ added in v0.0.3
FMAExact is similar to Decimal.FMA, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will panic. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("5.7") e := decimal.MustParse("3") f := decimal.MustParse("2.8") fmt.Println(d.FMAExact(e, f, 2)) }
Output: 19.90
func (Decimal) Floor ¶
Floor returns d that is rounded down to the specified number of digits after the decimal point. If the scale of d is less than the specified scale, the result will be zero-padded to the right. Also see method Decimal.Ceil.
Floor panics if:
- the integer part of the result has more than (MaxPrec - scale) digits;
- the scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") fmt.Println(d.Floor(6)) fmt.Println(d.Floor(5)) fmt.Println(d.Floor(4)) fmt.Println(d.Floor(3)) fmt.Println(d.Floor(2)) fmt.Println(d.Floor(1)) fmt.Println(d.Floor(0)) }
Output: 15.679000 15.67900 15.6790 15.679 15.67 15.6 15
func (Decimal) Format ¶
Format implements fmt.Formatter interface. The following verbs are available:
%f, %s, %v: -123.456 %q: "-123.456" %k: -12345.6%
The following format flags can be used with all verbs: '+', ' ', '0', '-'.
Precision is only supported for %f and %k verbs. For %f verb, the default precision is equal to the actual scale of the decimal, whereas, for verb %k the default precision is the actual scale of the decimal minus 2.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.679") fmt.Printf("%k\n", d) fmt.Printf("%f\n", d) fmt.Printf("%.2f\n", d) }
Output: -1567.9% -15.679 -15.68
func (Decimal) IsInt ¶
IsInt returns true if fractional part of d is zero.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("1.00") e := decimal.MustParse("1.01") fmt.Println(d.IsInt()) fmt.Println(e.IsInt()) }
Output: true false
func (Decimal) IsNeg ¶
IsNeg returns true if d is less than zero.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("23") f := decimal.MustParse("0") fmt.Println(d.IsNeg()) fmt.Println(e.IsNeg()) fmt.Println(f.IsNeg()) }
Output: true false false
func (Decimal) IsOne ¶
IsOne returns true if d is positive one or negative one.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("1") e := decimal.MustParse("2") fmt.Println(d.IsOne()) fmt.Println(e.IsOne()) }
Output: true false
func (Decimal) IsPos ¶
IsPos returns true if d is greater than zero.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("23") f := decimal.MustParse("0") fmt.Println(d.IsPos()) fmt.Println(e.IsPos()) fmt.Println(f.IsPos()) }
Output: false true false
func (Decimal) IsZero ¶
IsZero returns true if d is zero.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("23") f := decimal.MustParse("0") fmt.Println(d.IsZero()) fmt.Println(e.IsZero()) fmt.Println(f.IsZero()) }
Output: false false true
func (Decimal) LessThanOne ¶
LessThanOne returns true if d greater than negative one and less than positive one.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("1") e := decimal.MustParse("0.9") f := decimal.MustParse("-1") fmt.Println(d.LessThanOne()) fmt.Println(e.LessThanOne()) fmt.Println(f.LessThanOne()) }
Output: false true false
func (Decimal) MarshalText ¶
MarshalText implements encoding.TextMarshaler interface. Also see method Decimal.String.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") b, err := d.MarshalText() if err != nil { panic(err) } fmt.Println(string(b)) }
Output: -15.67
func (Decimal) Max ¶
Max returns maximum of d and e. Also see method Decimal.CmpTotal
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23") e := decimal.MustParse("-15.67") fmt.Println(d.Max(e)) }
Output: 23
func (Decimal) Min ¶
Min returns minimum of d and e. Also see method Decimal.CmpTotal
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23") e := decimal.MustParse("-15.67") fmt.Println(d.Min(e)) }
Output: -15.67
func (Decimal) MinScale ¶
MinScale returns the smallest scale that d can be rescaled to without rounding. Also see method Decimal.Reduce.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23.0000") e := decimal.MustParse("-15.6700") fmt.Println(d.MinScale()) fmt.Println(e.MinScale()) }
Output: 0 2
func (Decimal) Mul ¶
Mul returns (possibly rounded) product of d and e.
Mul panics if the integer part of the product has more than MaxPrec digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("5.7") e := decimal.MustParse("3") fmt.Println(d.Mul(e)) }
Output: 17.1
func (Decimal) MulExact ¶
MulExact is similar to Decimal.Mul, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will panic. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("5.7") e := decimal.MustParse("3") fmt.Println(d.MulExact(e, 2)) }
Output: 17.10
func (Decimal) Neg ¶
Neg returns d with opposite sign.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.67") fmt.Println(d.Neg()) }
Output: -15.67
func (Decimal) Pow ¶
Pow returns (possibly rounded) d raised to the exp.
Pow panics if the integer part of the power has more than MaxPrec digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("2") fmt.Println(d.Pow(-3)) fmt.Println(d.Pow(-2)) fmt.Println(d.Pow(-1)) fmt.Println(d.Pow(0)) fmt.Println(d.Pow(1)) fmt.Println(d.Pow(2)) fmt.Println(d.Pow(3)) }
Output: 0.125 0.25 0.5 1 2 4 8
func (Decimal) Prec ¶
Prec returns number of digits in the coefficient.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-123") e := decimal.MustParse("5.7") f := decimal.MustParse("0.4") fmt.Println(d.Prec()) fmt.Println(e.Prec()) fmt.Println(f.Prec()) }
Output: 3 2 1
func (Decimal) Quantize ¶
Quantize returns d that is rounded to the same scale as e. The sign and coefficient of y are ignored. Also see method Decimal.Round.
Qunatize panics if the integer part of d has more than (MaxPrec - e.Scale()) digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") x := decimal.MustParse("0.01") y := decimal.MustParse("0.1") z := decimal.MustParse("1") fmt.Println(d.Quantize(x)) fmt.Println(d.Quantize(y)) fmt.Println(d.Quantize(z)) }
Output: 15.68 15.7 16
func (Decimal) Quo ¶
Quo returns (possibly rounded) quotient of d and e.
Quo panics if:
- the integer part of the quotient has more than MaxPrec digits;
- the divisor is 0.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("2") fmt.Println(d.Quo(e)) }
Output: -7.835
func (Decimal) QuoExact ¶
QuoExact is similar to Decimal.Quo, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will panic. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("2") fmt.Println(d.QuoExact(e, 6)) }
Output: -7.835000
func (Decimal) QuoRem ¶
QuoRem returns the quotient and remainder of d and e such that d = q * e + r.
QuoRem panics if:
- the integer part of the quotient has more than MaxPrec digits;
- the divisor is 0.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("2") fmt.Println(d.QuoRem(e)) }
Output: -7 -1.67
func (Decimal) Reduce ¶
Reduce returns d with all trailing zeros removed.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23.0000") e := decimal.MustParse("-15.6700") fmt.Println(d.Reduce()) fmt.Println(e.Reduce()) }
Output: 23 -15.67
func (Decimal) Round ¶
Round returns d that is rounded to the specified number of digits after the decimal point. If the scale of d is less than the specified scale, the result will be zero-padded to the right. For financial calculations, the scale should be equal to or greater than the scale of the currency.
Round panics if:
- the integer part of the result has more than (MaxPrec - scale) digits;
- the scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") fmt.Println(d.Round(6)) fmt.Println(d.Round(5)) fmt.Println(d.Round(4)) fmt.Println(d.Round(3)) fmt.Println(d.Round(2)) fmt.Println(d.Round(1)) fmt.Println(d.Round(0)) }
Output: 15.679000 15.67900 15.6790 15.679 15.68 15.7 16
func (Decimal) Scale ¶
Scale returns number of digits after the decimal point.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("23.0000") e := decimal.MustParse("-15.670") fmt.Println(d.Scale()) fmt.Println(e.Scale()) }
Output: 4 3
func (Decimal) Sign ¶
Sign returns:
-1 if d < 0 0 if d == 0 +1 if d > 0
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-15.67") e := decimal.MustParse("23") f := decimal.MustParse("0") fmt.Println(d.Sign()) fmt.Println(e.Sign()) fmt.Println(f.Sign()) }
Output: -1 1 0
func (Decimal) String ¶
String method implements the fmt.Stringer interface and returns a string representation of a decimal value. The returned string does not use scientific or engineering notation and is formatted according to the following formal EBNF grammar:
sign ::= '-' digits ::= { '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' } significand ::= digits '.' digits | digits numeric-string ::= [sign] significand
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("1234567890.123456789") fmt.Println(d.String()) }
Output: 1234567890.123456789
func (Decimal) Sub ¶
Sub returns (possibly rounded) difference of d and e.
Sub panics if the integer part of the difference has more than MaxPrec digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.6") e := decimal.MustParse("8") fmt.Println(d.Sub(e)) }
Output: 7.6
func (Decimal) SubExact ¶
SubExact is similar to Decimal.Sub, but it allows you to specify how many digits after the decimal point should be considered significant. If any of the significant digits are lost during rounding, the method will panic. This method is useful for financial calculations, where the scale should be equal to or greater than the currency's scale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.6") e := decimal.MustParse("8") fmt.Println(d.SubExact(e, 2)) }
Output: 7.60
func (Decimal) Trunc ¶
Trunc returns d that is truncated to the specified number of digits after the decimal point. If the scale of d is less than the specified scale, the result will be zero-padded to the right. Also see method Decimal.Reduce.
Trunc panics if:
- the integer part of the result has more than (MaxPrec - scale) digits;
- the scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") fmt.Println(d.Trunc(6)) fmt.Println(d.Trunc(5)) fmt.Println(d.Trunc(4)) fmt.Println(d.Trunc(3)) fmt.Println(d.Trunc(2)) fmt.Println(d.Trunc(1)) fmt.Println(d.Trunc(0)) }
Output: 15.679000 15.67900 15.6790 15.679 15.67 15.6 15
func (Decimal) ULP ¶ added in v0.0.6
ULP (Unit in the Last Place) returns the smallest representable positive difference between d and the next larger decimal value with the same number of digits.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("-1.23") e := decimal.MustParse("0.0") f := decimal.MustParse("15") fmt.Println(d.ULP()) fmt.Println(e.ULP()) fmt.Println(f.ULP()) }
Output: 0.01 0.1 1
func (*Decimal) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler interface. Also see method Parse.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := &decimal.Decimal{} b := []byte("-15.67") err := d.UnmarshalText(b) if err != nil { panic(err) } fmt.Println(d) }
Output: -15.67
func (Decimal) WithScale ¶
WithScale returns d with specified scale. Also see method Decimal.Round.
WithScale panics if the scale is less than 0 or greater than MaxScale.
Example ¶
package main import ( "fmt" "github.com/govalues/decimal" ) func main() { d := decimal.MustParse("15.679") fmt.Println(d.WithScale(6)) fmt.Println(d.WithScale(5)) fmt.Println(d.WithScale(4)) fmt.Println(d.WithScale(3)) fmt.Println(d.WithScale(2)) fmt.Println(d.WithScale(1)) fmt.Println(d.WithScale(0)) }
Output: 0.015679 0.15679 1.5679 15.679 156.79 1567.9 15679