# decimal

package module
Version: v0.0.8 Latest Latest

Go to latest
Published: Mar 25, 2023 License: MIT

### Decimal

Package decimal implements immutable decimal floating-point numbers for Go.

#### Getting started

To install the decimal package into your Go workspace, you can use the go get command:

``````go get github.com/govalues/decimal
``````

To use the decimal package in your Go project, you can import it as follows:

``````import "github.com/govalues/decimal"
``````

#### Using Decimal

To create a new Decimal value, you can use one of the provided constructors, such as `New`, `Parse` or `MustParse`.

``````x := decimal.New(12345, 2) // x = 123,45
y := decimal.MustParse("123.45")
``````

Once you have a Decimal value, you can perform arithmetic operations such as addition, subtraction, multiplication, division, and exponentiation, as well as rounding operations such as ceiling, floor, truncation, and rounding.

``````sum := x.Add(y)
difference := x.Sub(y)
product := x.Mul(y)
quotient := x.Quo(y)
power := x.Pow(5)
ceil := x.Ceil(0)
floor := x.Floor(0)
trunc := x.Trunc(0)
round := x.Round(0)
``````

For more details on these and other methods, see the package documentation at pkg.go.dev.

#### Benchmarks

``````goos: linux
goarch: amd64
pkg: github.com/govalues/benchmarks
cpu: AMD Ryzen 7 3700C  with Radeon Vega Mobile Gfx
``````
Test Case Expression govalues cockroachdb v3.1.2 cockroachdb vs govalues shopspring v1.3.1 shopspring vs govalues
Decimal_Add 2 + 3 16.32n 46.76n +186.49% 138.75n +750.18%
Decimal_Mul 2 * 3 15.81n 51.41n +225.21% 135.90n +759.58%
Decimal_QuoFinite 2 / 4 78.36n 379.50n +384.30% 641.60n +718.79%
Decimal_QuoInfinite 2 / 3 573.7n 948.4n +65.31% 2828.5n +393.03%
Decimal_Pow 1.1^60 1.029µ 3.078µ +199.08% 19.949µ +1838.68%
Parse - 106.6n 252.1n +136.60% 497.5n +366.92%
Decimal_String - 138.2n 194.8n +40.99% 329.3n +138.28%

The benchmark results shown in the table are provided for informational purposes only and may vary depending on your specific use case.

#### Contributing to the project

The Decimal package is hosted on GitHub. To contribute to the project, follow these steps:

1. Fork the repository and clone it to your local machine.
2. Make the desired changes to the code.
3. Write tests for the changes you made.
4. Ensure that all tests pass by running `go test`.
5. Commit the changes and push them to your fork.
6. Submit a pull request with a clear description of the changes you made.
7. Wait for the maintainers to review and merge your changes.

Note: Before making any significant changes to the code, it is recommended to open an issue to discuss the proposed changes with the maintainers. This will help to ensure that the changes align with the project's goals and roadmap.

## 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:

1. 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.

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:

#### 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:

#### Errors ¶

Arithmetic operations panic in the following cases:

1. 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.

2. 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.

3. 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++ {
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 "+":
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
```

### Constants ¶

View Source
```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 ¶

`func MustParse(num string) Decimal`

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 ¶

`func New(coef int64, scale int) Decimal`

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 ¶

`func Parse(num string) (Decimal, error)`

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 ¶

`func ParseExact(num string, scale int) (Decimal, error)`

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 ¶

`func (d Decimal) Abs() Decimal`

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 (d Decimal) Add(e Decimal) Decimal`

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")
}
```
```Output:

23.6
```

`func (d Decimal) AddExact(e Decimal, scale int) Decimal`

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")
}
```
```Output:

23.60
```

#### func (Decimal) Ceil ¶

`func (d Decimal) Ceil(scale int) Decimal`

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 ¶

`func (d Decimal) Cmp(e Decimal) int`

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 ¶

`func (d Decimal) CmpTotal(e Decimal) int`

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 ¶

`func (d Decimal) Coef() uint64`

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

`func (d Decimal) CopySign(e Decimal) Decimal`

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

`func (d Decimal) FMA(e, f Decimal) Decimal`

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

`func (d Decimal) FMAExact(e, f Decimal, scale int) Decimal`

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 ¶

`func (d Decimal) Floor(scale int) Decimal`

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 ¶

`func (d Decimal) Format(state fmt.State, verb rune)`

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 ¶

`func (d Decimal) IsInt() bool`

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 ¶

`func (d Decimal) IsNeg() bool`

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 ¶

`func (d Decimal) IsOne() bool`

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 ¶

`func (d Decimal) IsPos() bool`

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 ¶

`func (d Decimal) IsZero() bool`

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 ¶

`func (d Decimal) LessThanOne() bool`

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 ¶

`func (d Decimal) MarshalText() ([]byte, error)`

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 ¶

`func (d Decimal) Max(e Decimal) Decimal`

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 ¶

`func (d Decimal) Min(e Decimal) Decimal`

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 ¶

`func (d Decimal) MinScale() int`

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 ¶

`func (d Decimal) Mul(e Decimal) Decimal`

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 ¶

`func (d Decimal) MulExact(e Decimal, scale int) Decimal`

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 ¶

`func (d Decimal) Neg() Decimal`

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 ¶

`func (d Decimal) Pow(exp int) Decimal`

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 ¶

`func (d Decimal) Prec() int`

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 ¶

`func (d Decimal) Quantize(e Decimal) Decimal`

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 ¶

`func (d Decimal) Quo(e Decimal) Decimal`

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 ¶

`func (d Decimal) QuoExact(e Decimal, scale int) Decimal`

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 ¶

`func (d Decimal) QuoRem(e Decimal) (Decimal, Decimal)`

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 ¶

`func (d Decimal) Reduce() Decimal`

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 ¶

`func (d Decimal) Round(scale int) Decimal`

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 ¶

`func (d Decimal) Scale() int`

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 ¶

`func (d Decimal) Sign() int`

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 ¶

`func (d Decimal) String() 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 ¶

`func (d Decimal) Sub(e Decimal) Decimal`

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 ¶

`func (d Decimal) SubExact(e Decimal, scale int) Decimal`

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 ¶

`func (d Decimal) Trunc(scale int) Decimal`

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

`func (d Decimal) ULP() Decimal`

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 ¶

`func (d *Decimal) UnmarshalText(text []byte) error`

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 ¶

`func (d Decimal) WithScale(scale int) Decimal`

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
```