decimal
Package decimal implements immutable decimal floating-point numbers for Go.
This package is designed specifically for use in transactional financial systems.
Features
- Immutability - Once a decimal is set, it remains unchanged.
This immutability ensures safe concurrent access across goroutines.
- Banker's Rounding - Methods use half-to-even rounding, also known as
"banker's rounding", which minimizes cumulative rounding errors commonly seen
in financial calculations.
- No Panics - All methods are designed to be panic-free.
Instead of potentially crashing your application, they return errors for issues
such as overflow or division by zero.
- Zero Heap Allocation - Methods are optimized to avoid heap allocations,
reducing the impact on the garbage collector during arithmetic operations.
- Simple String Representation - Decimals are represented in a strightforward
format avoiding the complexities of scientific or engineering notations.
- Correctness - Fuzz testing is used to cross-validate arithmetic operations
against the cockroachdb/apd and shopspring/decimal packages.
Getting Started
Installation
To add the decimal package to your Go workspace:
go get github.com/govalues/decimal
Usage
Create decimal values using one of the constructors.
After creating a decimal value, various operations can be performed:
package main
import (
"fmt"
"github.com/govalues/decimal"
)
func main() {
d, _ := decimal.New(8, 0)
e, _ := decimal.Parse("12.5")
f, _ := decimal.NewFromFloat64(2.567)
g, _ := decimal.NewFromInt64(7, 896, 3)
fmt.Println(d.Add(e))
fmt.Println(d.Sub(e))
fmt.Println(d.Mul(e))
fmt.Println(d.FMA(e, f))
fmt.Println(d.Pow(2))
fmt.Println(d.Quo(e))
fmt.Println(d.QuoRem(e))
fmt.Println(d.Inv())
fmt.Println(g.Round(2))
fmt.Println(g.Ceil(2))
fmt.Println(g.Floor(2))
fmt.Println(g.Trunc(2))
fmt.Println(f.Int64(9))
fmt.Println(f.Float64())
fmt.Println(f.String())
fmt.Printf("%.2f\n", f)
fmt.Printf("%.2k\n", f)
}
Documentation
For detailed documentation and additional examples, visit the package
documentation.
For examples related to financial calculations, see the money
package
documentation.
Comparison
Comparison with other popular packages:
Feature | govalues | cockroachdb/apd v3.2.1 | shopspring/decimal v1.3.1 |
---|
Speed | High | Medium | Low1 |
Mutability | Immutable | Mutable1 | Immutable |
Memory Footprint | Low | Medium | High |
Panic Free | Yes | Yes | No2 |
Precision | 19 digits | Arbitrary | Arbitrary |
Default Rounding | Half to even | Half up | Half away from 0 |
Context | Implicit | Explicit | Implicit |
Benchmarks
goos: linux
goarch: amd64
pkg: github.com/govalues/decimal-tests
cpu: AMD Ryzen 7 3700C with Radeon Vega Mobile Gfx
Test Case | Expression | govalues | cockroachdb/apd v3.2.1 | shopspring/decimal v1.3.1 | govalues vs cockroachdb | govalues vs shopspring |
---|
Add | 5 + 6 | 16.89n | 80.96n | 140.50n | +379.48% | +732.10% |
Mul | 2 * 3 | 16.85n | 58.14n | 145.30n | +245.15% | +762.57% |
QuoExact | 2 ÷ 4 | 66.00n | 193.25n | 619.15n | +192.78% | +838.03% |
QuoInfinite | 2 ÷ 3 | 453.30n | 961.00n | 2767.00n | +112.01% | +510.41% |
Pow | 1.1^60 | 1.04µ | 3.42µ | 15.76µ | +227.72% | +1408.43% |
Pow | 1.01^600 | 3.57µ | 10.70µ | 35.70µ | +200.11% | +901.23% |
Pow | 1.001^6000 | 6.19µ | 20.72µ | 634.41µ | +234.65% | +10148.95% |
Parse | 1 | 16.98n | 80.98n | 132.40n | +376.91% | +679.74% |
Parse | 123.456 | 50.80n | 195.05n | 246.10n | +283.92% | +384.40% |
Parse | 123456789.1234567890 | 96.36n | 239.60n | 516.20n | +148.64% | +435.67% |
String | 1 | 5.70n | 20.89n | 203.25n | +266.24% | +3464.23% |
String | 123.456 | 42.74n | 75.71n | 235.65n | +77.14% | +451.36% |
String | 123456789.1234567890 | 72.34n | 215.90n | 331.20n | +198.47% | +357.87% |
Telco | see specification | 148.00n | 1075.00n | 4010.50n | +626.35% | +2609.80% |
The benchmark results shown in the table are provided for informational purposes only and may vary depending on your specific use case.
Contributing
Interested in contributing? Here's how to get started:
- Fork and clone the repository.
- Implement your changes.
- Write tests to cover your changes.
- Ensure all tests pass with
go test
. - Commit and push to your fork.
- Open a pull request detailing your changes.
Note: If you're considering significant changes, please open an issue first to
discuss with the maintainers.
This ensures alignment with the project's objectives and roadmap.