Library / SDK
shopspring/decimal avatar
shopspring/decimal

shopspring/decimal: arbitrary-precision fixed-point decimals in Go

Arbitrary-precision fixed-point decimal numbers in Go

7,484 stars679 forksGoNOASSERTION

At a glance

What is it?
A Go library for money arithmetic that avoids binary floating point error, with an immutable API and a deliberate performance trade-off. It fits billing and ledger code; it is the wrong tool for scientific computation and for hot paths where allocations matter.
Who is it for?
Adopt shopspring/decimal when your Go code stores or computes monetary amounts and you want an immutable value type that serializes through database/sql, JSON and XML without binary float error.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 41 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem shopspring/decimal solves for Go money code

Binary floating point cannot represent 0.1 exactly. The README makes this the central argument: the same calculation that a reader expects to print 10 prints 9.999999999999831 instead, and the README notes that over time these small errors add up. For a shopping cart, an invoice or a ledger, that drift is a correctness bug, not a rounding curiosity. shopspring/decimal represents numbers as fixed-point decimals with arbitrary precision, so the value you parse is the value you store and print. The audience is Go developers handling currency, tax rates, unit prices and quantities. The library also targets persistence: the feature list names database/sql serialization and deserialization plus JSON and XML serialization, which is the practical work of moving a money value between an API, a database column and application code without a lossy intermediate step. If your amounts are counters, durations or measurements rather than money, this is not the library you want.

Immutability as the core design decision

Every Decimal method returns a new Decimal and none of them modify the receiver. The README contrasts this directly with big.Int, whose API is built to reduce allocations: adding two big.Ints looks like z := new(big.Int).Add(x, y), and a developer who writes z := a.Add(a, b) silently modifies a and every alias of a. The README links a playground example of that class of bug. Decimal removes the failure mode by construction. Assignment still does not deep copy, so two variables can refer to the same value, but since no method mutates, that aliasing is harmless. The README is explicit that the cost is extra allocations and lower performance, and states the assumption behind the choice: if you are using decimals, you probably care more about correctness than performance. That is an honest framing of a real trade-off rather than a claim of having both.

Installing shopspring/decimal and running the README example

The README gives one install step and one requirement. Run the go get command below from a module, and note that the library requires Go version >=1.10, which is also what the repository go.mod declares. The README points to godoc for the full API surface.

bash
go get github.com/shopspring/decimal

The README usage example builds a subtotal, applies a fee, then applies a tax rate. Parse the price with NewFromString, which returns an error you should not discard in real code, and build whole numbers with NewFromInt. The output comments in the README are the expected results.

go
package main

import (
	"fmt"

	"github.com/shopspring/decimal"
)

func main() {
	price, err := decimal.NewFromString("136.02")
	if err != nil {
		panic(err)
	}
	quantity := decimal.NewFromInt(3)
	subtotal := price.Mul(quantity)
	fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
}

The README also shows decimal.NewFromFloat(1) being added to a parsed rate before multiplying, and a final step where the effective tax rate is recovered with total.Sub(preTax).Div(preTax), printing 0.08875. Division is the operation to read carefully: the README lists division with specified precision as a feature, so the precision argument is yours to choose and it determines the result.

Where shopspring/decimal is the wrong tool

The README opens with a limitation rather than burying it: the library can only represent numbers with a maximum of 2^31 digits after the decimal point. That ceiling is far beyond any monetary amount, but it is a ceiling, and it tells you the representation is fixed point rather than an unbounded rational. The second limitation is performance, and the README states it plainly: the immutable API causes extra allocations, and the library is less performant than big.Int-style mutation. In a tight loop that converts and multiplies millions of values, that allocation cost is the dominant factor, and the README's own alternative list points at libraries chosen specifically for speed. The third case is rational arithmetic. The README's big.Rat example is instructive: with precision 3, x and y both become 0.333 rather than 1/3, so z = 1 - x - y is .334 and no money is unaccounted for. That is the behaviour you want for currency and the behaviour you do not want if you need exact rational values. Splitting an amount N three ways still requires care: the README says you cannot send N/3 to three people, you must pick one recipient to receive N - (2/3*N) and absorb the remainder. The library does not do that allocation for you.

How shopspring/decimal compares with the alternatives it names

The README lists four alternatives, and the differences are about precision and allocation strategy rather than features. cockroachdb/apd is described as arbitrary precision with a mutable, rich API similar to big.Int, and the README says it is more performant than this library. alpacahq/alpacadecimal is described as high performance with low precision, 12 digits, and a fully compatible API with this library, which means it can be a drop-in replacement if your amounts fit that range. govalues/decimal is described as high performance and zero-allocation, with 19 digits of precision. greatcloak/decimal is a fork focused on billing and e-commerce use cases, and it adds out-of-the-box BSON marshaling, which matters if you persist to MongoDB and do not want to write that marshaling yourself. The pattern is consistent: if you need arbitrary precision and an immutable API, stay here; if you have measured an allocation problem and your values fit a smaller range, the README itself points you at faster options.

Maintenance, upgrades and the licence question

The last push to the default branch was on 2026-08-19, and the repository is not archived. Releases are infrequent rather than continuous: v1.3.0 and v1.3.1 landed in October 2021, and v1.4.0 on 2024-04-12. The go.mod declares go 1.10, so the module makes no demands on a modern toolchain, which lowers the cost of pinning an older version. The CHANGELOG.md at the repository root is where the project records version-to-version changes, and it is the file to read before moving a pinned version. The README states the licence as The MIT License (MIT) and notes that the library is a heavily modified fork of fpd.Decimal, also released under the MIT License. The repository metadata reports the licence as NOASSERTION, which means automated licence detection did not reach a conclusion; the README and the LICENSE file are the sources to check. That is a fact about detection, not about the terms, and it is not legal advice.

Editorial conclusion

Adopt shopspring/decimal when your Go code stores or computes monetary amounts and you want an immutable value type that serializes through database/sql, JSON and XML without binary float error. Do not adopt it for scientific or statistical computation, where arbitrary-precision fixed point is the wrong representation, and do not adopt it in allocation-sensitive inner loops without measuring first, because the README states that returning new values instead of mutating causes extra allocations. Before you commit, verify three things: the exact rounding behaviour of Div at the precision you pass, how your database driver maps the value on scan, and whether your amounts can exceed the ranges a 2^31-digit scale makes practical.

Frequently asked questions

How do I install shopspring/decimal in a Go project?

Run go get github.com/shopspring/decimal. The README states the library requires Go version >=1.10, which matches the go.mod in the repository.

Why does shopspring/decimal exist instead of just using float64?

Because float64 cannot represent numbers such as 0.1 exactly. The README gives an example where code expected to print 10 prints 9.999999999999831, and notes that these small errors add up over time.

What is the maximum number of decimal places shopspring/decimal supports?

The README states the library can only represent numbers with a maximum of 2^31 digits after the decimal point.

Is shopspring/decimal slower than big.Int because its API is immutable?

The README says the immutable API causes extra allocations and that Decimal is less performant than big.Int's mutating style. The stated assumption is that users of decimals care more about correctness than performance.

What licence is shopspring/decimal released under?

The README states The MIT License (MIT) and describes the library as a heavily modified fork of fpd.Decimal, which was also released under the MIT License. The repository metadata reports NOASSERTION, so the README and LICENSE file are the sources to check.

Official sources

  1. Issues
  2. README
  3. Releases
  4. shopspring/decimal on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/shopspring-decimal.svg)](https://hysenlabs.com/projects/shopspring-decimal)