Categorygithub.com/govalues/decimal
modulepackage
0.1.29
Repository: https://github.com/govalues/decimal.git
Documentation: pkg.go.dev

# README

decimal

githubb codecovb goreportb godocb licenseb versionb awesomeb

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() {
    // Constructors
    d, _ := decimal.New(8, 0)               // d = 8
    e, _ := decimal.Parse("12.5")           // e = 12.5
    f, _ := decimal.NewFromFloat64(2.567)   // f = 2.567
    g, _ := decimal.NewFromInt64(7, 896, 3) // g = 7.896

    // Operations
    fmt.Println(d.Add(e))          // 8 + 12.5
    fmt.Println(d.Sub(e))          // 8 - 12.5

    fmt.Println(d.Mul(e))          // 8 * 12.5
    fmt.Println(d.FMA(e, f))       // 8 * 12.5 + 2.567
    fmt.Println(d.Pow(2))          // 8²
    fmt.Println(d.Sqrt())          // √8

    fmt.Println(d.Quo(e))          // 8 ÷ 12.5
    fmt.Println(d.QuoRem(e))       // 8 div 12.5, 8 mod 12.5
    fmt.Println(d.Inv())           // 1 ÷ 8

    // Rounding to 2 decimal places
    fmt.Println(g.Round(2))        // 7.90
    fmt.Println(g.Ceil(2))         // 7.90
    fmt.Println(g.Floor(2))        // 7.89
    fmt.Println(g.Trunc(2))        // 7.89

    // Conversions
    fmt.Println(f.Int64(9))        // 2 567000000
    fmt.Println(f.Float64())       // 2.567
    fmt.Println(f.String())        // 2.567

    // Formatting
    fmt.Printf("%.2f\n", f)        // 2.57
    fmt.Printf("%.2k\n", f)        // 256.70%
}

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:

Featuregovaluescockroachdb/apd v3.2.1shopspring/decimal v1.4.0
SpeedHighMediumLow1
MutabilityImmutableMutable1Immutable
Memory FootprintLowMediumHigh
Panic FreeYesYesNo2
Precision19 digitsArbitraryArbitrary
Default RoundingHalf to evenHalf upHalf away from 0
ContextImplicitExplicitImplicit

Benchmarks

goos: linux
goarch: amd64
pkg: github.com/govalues/decimal-tests
cpu: AMD Ryzen 7 3700C  with Radeon Vega Mobile Gfx 
Test CaseExpressiongovaluescockroachdb/apd v3.2.1shopspring/decimal v1.4.0govalues vs cockroachdbgovalues vs shopspring
Add5 + 616.06n74.88n140.90n+366.22%+777.33%
Mul2 * 316.93n62.20n146.00n+267.40%+762.37%
QuoExact2 ÷ 459.52n176.95n657.40n+197.30%+1004.50%
QuoInfinite2 ÷ 3391.60n976.80n2962.50n+149.39%+656.42%
Pow1.1^60950.90n3302.50n4599.50n+247.32%+383.73%
Pow1.01^6003.45µ10.67µ18.67µ+209.04%+440.89%
Pow1.001^60005.94µ20.50µ722.22µ+244.88%+12052.44%
Sqrt√23.40µ4.96µ2101.86µ+46.00%+61755.71%
Parse116.52n76.30n136.55n+362.00%+726.82%
Parse123.45647.37n176.90n242.60n+273.44%+412.14%
Parse123456789.123456789085.49n224.15n497.95n+162.19%+482.47%
String15.11n19.57n198.25n+283.21%+3783.07%
String123.45635.78n77.12n228.85n+115.52%+539.51%
String123456789.123456789070.72n239.10n337.25n+238.12%+376.91%
Telcosee specification137.00n969.40n3981.00n+607.33%+2804.78%

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

Footnotes

  1. decimal package was created simply because shopspring/decimal was too slow and cockroachdb/apd was mutable. 2

  2. shopspring/decimal panics on division by zero.

# Functions

MustNew is like [New] but panics if the decimal cannot be constructed.
MustParse is like [Parse] but panics if the string cannot be parsed.
New returns a decimal equal to coef / 10^scale.
NewFromFloat64 converts a float to a (possibly rounded) decimal.
NewFromInt64 converts a pair of integers, representing the whole and fractional parts, to a (possibly rounded) decimal equal to whole + frac / 10^scale.
Parse converts a string to a (possibly rounded) decimal.
ParseExact is similar to [Parse], but it allows you to specify how many digits after the decimal point should be considered significant.

# Constants

MaxPrec is a maximum length of the coefficient in decimal digits.
MaxScale is a maximum number of digits after the decimal point.
MinScale is a minimum number of digits after the decimal point.

# Variables

E represents Euler’s number rounded to 18 digits.
Hundred represents the decimal value of 100.
NegOne represents the decimal value of -1.
One represents the decimal value of 1.
Pi represents the value of π rounded to 18 digits.
Ten represents the decimal value of 10.
Thousand represents the decimal value of 1,000.
Two represents the decimal value of 2.
Zero represents the decimal value of 0.

# Structs

Decimal represents a finite floating-point decimal number.
NullDecimal represents a decimal that can be null.