Skip to content

jokruger/dec128

Repository files navigation

dec128

Go Reference Go Report Card codecov Mentioned in Awesome Go

High performance 128-bit fixed-point decimal numbers in go.

Key Objectives / Features

  • High performance
  • Zero dependencies
  • Minimal or zero memory allocation
  • Scale up to 19 decimal places
  • Fixed size memory layout (128 bits)
  • No panic or error arithmetics (use NaN instead)
  • Immutability (methods return new instances)
  • Basic arithmetic operations required for financial calculations (specifically for banking and accounting)
  • Additional arithmetic operations for scientific calculations
  • Easy to use
  • Easy to integrate with external systems (e.g. databases, accounting systems, JSON, etc.)
  • Financially correct rounding
  • Correct comparison of numbers encoded in different scales (e.g. 1.0 == 1.00)
  • Correct handling of NaN values (e.g. NaN + 1 = NaN)
  • Conversion to canonical representation (e.g. 1.0000 -> 1)
  • Conversion to fixed string representation (e.g. 1.0000 -> "1.0000")
  • Conversion to human-readable string representation (e.g. 1.0000 -> "1")

Install

Run go get github.com/jokruger/dec128

Requirements

This library requires Go version >=1.23

Documentation

http://godoc.org/github.com/jokruger/dec128

Usage

package main

import (
    "fmt"
    "github.com/jokruger/dec128"
)

func main() {
    principal := dec128.FromString("1000.00")
    annualRate := dec128.FromString("5.0")
    days := 30

    dailyRate := annualRate.Div(dec128.FromInt64(365))
    dailyRate = dailyRate.Div(dec128.FromInt64(100))

    accruedInterest := principal.Mul(dailyRate).Mul(dec128.FromInt64(days)).RoundBank(2)

    fmt.Printf("Principal: %v\n", principal.StringFixed())
    fmt.Printf("Annual Interest Rate: %v\n", annualRate.String())
    fmt.Printf("Days: %v\n", days)
    fmt.Printf("Accrued Interest: %v\n", accruedInterest.String())

    total := principal.Add(accruedInterest).RoundBank(2)
    fmt.Printf("Total after %v days: %v\n", days, total.StringFixed())
}

Why not use other libraries?

There are several other libraries that provide decimal arithmetic in Go. However, most of them are either too slow, too memory-intensive, or lack the integration features required for financial applications. This library aims to provide a high-performance, low-memory, and easy-to-use alternative to existing libraries.

Benchmarks

The following benchmarks were run on a MacBook Pro (2019) with a 2.6 GHz 6-Core Intel Core i7 processor and 16 GB of RAM (https://github.com/jokruger/go-decimal-benchmark).

                                 parse (ns/op)  string (ns/op)     add (ns/op)     mul (ns/op)     div (ns/op)

dec128.Dec128                           14.024          33.683           9.975           6.569          35.116
udecimal.Decimal                        23.302          41.854          12.226          11.346          40.877
alpacadecimal.Decimal                   89.528          78.884         206.393          60.364         451.828
shopspring.Decimal                     152.263         169.300         218.909          65.241         428.002

Notes on Terminology

  • Scale: Number of digits after the decimal point. For example, 1.00 has scale of 2 and 1.0000 has scale of 4.
  • Exponent: Same as scale, but in the context of low-level implementation details or Dec128 encoding.
  • Canonical: The representation of a number with the minimum number of decimal places required to represent the number.
  • Quantum*: The smallest step at a given scale. For example, scale 2 has quantum 0.01

License

This project is licensed under the MIT License. See the LICENSE file for details.

Attribution

This project includes code derived from:

  • A project licensed under the BSD 3-Clause License (Copyright © 2025 Quang).
  • A project licensed under the MIT License (Copyright © 2019 Luke Champine).

See the LICENSE file for full license texts.