• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

.gitignoreH A D28-Apr-202036

.travis.ymlH A D28-Apr-2020107

CHANGELOG.mdH A D28-Apr-2020972

LICENSEH A D28-Apr-20202.2 KiB

README.mdH A D28-Apr-20204.6 KiB

decimal-go.goH A D28-Apr-202011 KiB

decimal.goH A D28-Apr-202038.8 KiB

decimal_bench_test.goH A D28-Apr-20203.4 KiB

decimal_test.goH A D28-Apr-202073.2 KiB

go.modH A D28-Apr-202046

rounding.goH A D28-Apr-20203.8 KiB

README.md

1# decimal
2
3[![Build Status](https://travis-ci.org/shopspring/decimal.png?branch=master)](https://travis-ci.org/shopspring/decimal) [![GoDoc](https://godoc.org/github.com/shopspring/decimal?status.svg)](https://godoc.org/github.com/shopspring/decimal) [![Go Report Card](https://goreportcard.com/badge/github.com/shopspring/decimal)](https://goreportcard.com/report/github.com/shopspring/decimal)
4
5Arbitrary-precision fixed-point decimal numbers in go.
6
7_Note:_ Decimal library can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
8
9## Features
10
11 * The zero-value is 0, and is safe to use without initialization
12 * Addition, subtraction, multiplication with no loss of precision
13 * Division with specified precision
14 * Database/sql serialization/deserialization
15 * JSON and XML serialization/deserialization
16
17## Install
18
19Run `go get github.com/shopspring/decimal`
20
21## Requirements
22
23Decimal library requires Go version `>=1.7`
24
25## Usage
26
27```go
28package main
29
30import (
31	"fmt"
32	"github.com/shopspring/decimal"
33)
34
35func main() {
36	price, err := decimal.NewFromString("136.02")
37	if err != nil {
38		panic(err)
39	}
40
41	quantity := decimal.NewFromInt(3)
42
43	fee, _ := decimal.NewFromString(".035")
44	taxRate, _ := decimal.NewFromString(".08875")
45
46	subtotal := price.Mul(quantity)
47
48	preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))
49
50	total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))
51
52	fmt.Println("Subtotal:", subtotal)                      // Subtotal: 408.06
53	fmt.Println("Pre-tax:", preTax)                         // Pre-tax: 422.3421
54	fmt.Println("Taxes:", total.Sub(preTax))                // Taxes: 37.482861375
55	fmt.Println("Total:", total)                            // Total: 459.824961375
56	fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
57}
58```
59
60## Documentation
61
62http://godoc.org/github.com/shopspring/decimal
63
64## Production Usage
65
66* [Spring](https://shopspring.com/), since August 14, 2014.
67* If you are using this in production, please let us know!
68
69## FAQ
70
71#### Why don't you just use float64?
72
73Because float64 (or any binary floating point type, actually) can't represent
74numbers such as `0.1` exactly.
75
76Consider this code: http://play.golang.org/p/TQBd4yJe6B You might expect that
77it prints out `10`, but it actually prints `9.999999999999831`. Over time,
78these small errors can really add up!
79
80#### Why don't you just use big.Rat?
81
82big.Rat is fine for representing rational numbers, but Decimal is better for
83representing money. Why? Here's a (contrived) example:
84
85Let's say you use big.Rat, and you have two numbers, x and y, both
86representing 1/3, and you have `z = 1 - x - y = 1/3`. If you print each one
87out, the string output has to stop somewhere (let's say it stops at 3 decimal
88digits, for simplicity), so you'll get 0.333, 0.333, and 0.333. But where did
89the other 0.001 go?
90
91Here's the above example as code: http://play.golang.org/p/lCZZs0w9KE
92
93With Decimal, the strings being printed out represent the number exactly. So,
94if you have `x = y = 1/3` (with precision 3), they will actually be equal to
950.333, and when you do `z = 1 - x - y`, `z` will be equal to .334. No money is
96unaccounted for!
97
98You still have to be careful. If you want to split a number `N` 3 ways, you
99can't just send `N/3` to three different people. You have to pick one to send
100`N - (2/3*N)` to. That person will receive the fraction of a penny remainder.
101
102But, it is much easier to be careful with Decimal than with big.Rat.
103
104#### Why isn't the API similar to big.Int's?
105
106big.Int's API is built to reduce the number of memory allocations for maximal
107performance. This makes sense for its use-case, but the trade-off is that the
108API is awkward and easy to misuse.
109
110For example, to add two big.Ints, you do: `z := new(big.Int).Add(x, y)`. A
111developer unfamiliar with this API might try to do `z := a.Add(a, b)`. This
112modifies `a` and sets `z` as an alias for `a`, which they might not expect. It
113also modifies any other aliases to `a`.
114
115Here's an example of the subtle bugs you can introduce with big.Int's API:
116https://play.golang.org/p/x2R_78pa8r
117
118In contrast, it's difficult to make such mistakes with decimal. Decimals
119behave like other go numbers types: even though `a = b` will not deep copy
120`b` into `a`, it is impossible to modify a Decimal, since all Decimal methods
121return new Decimals and do not modify the originals. The downside is that
122this causes extra allocations, so Decimal is less performant.  My assumption
123is that if you're using Decimals, you probably care more about correctness
124than performance.
125
126## License
127
128The MIT License (MIT)
129
130This is a heavily modified fork of [fpd.Decimal](https://github.com/oguzbilgic/fpd), which was also released under the MIT License.
131