decimal

package module
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 18, 2024 License: Apache-2.0 Imports: 12 Imported by: 3

README

decimal

This library implements fixed-precision decimal numbers based on the IEEE 754-2019 standard; https://ieeexplore.ieee.org/document/8766229. More info can be found at: http://speleotrove.com/decimal/

Features

  • Decimal64, partial implementation of the ieee-754R standard
  • Half up and half even rounding
  • Up to 3 times faster than arbitrary precision decimal libraries in Go

Goals

Installation and use

Run go get github.com/anz-bank/decimal

package main

import (
	"fmt"

	"github.com/anz-bank/decimal"
)

func main() {
	var a decimal.Decimal64
	b := decimal.MustParse64("0.1")
	c := decimal.MustParse64("0.3")
	d := decimal.New64FromInt64(123456)

	fmt.Println(a, b, c, d)
}

Usage notes

Formatting

Decimal64 provides numerous ways to present numbers for human and machine consumption.

Decimal64 implements the following conventional interfaces:

  • fmt: Formatter, Scanner and Stringer
  • json: Marshaller and Unmarshaller
  • encoding: BinaryMarshaler, BinaryUnmarshaler, TextMarshaler and TextUnmarshaler
  • encoging/gob: GobEncoder and GobDecoder

The following methods provide more direct access to the internal methods used to implement fmt.Formatter. (For maximum control, use fmt.Printf &co or invoke the fmt.Formatter interface directly.)

  • Decimal64.Append formats straight into a []byte buffer.
  • Decimal64.Text formats in the same way, but returns a string.
Debugging

tl;dr: Use the decimal_debug compiler tag during debugging to greatly ease runtime inspection of Decimal64 values.

Debugging with the decimal package can be challeging because a Decimal64 number is encoded in a uint64 and the values it holds are inscrutable even to the trained eye. For example, the number one decimal.One64 is represented internally as the number 3450757314565799936 (2fe38d7ea4c68000 in hexadecimal).

To ease debugging, Decimal64 holds an optional debugInfo structure that contains a string representation and unpacked components of the uint64 representation for every Decimal64 value.

This feature is enabled through the decimal_debug compiler tag. This is done at compile time instead of through runtime flags because having the structure there even if not used would double the size of each number and greatly increase the cost of using it. The size and runtime cost of this feature is zero when the compiler tag is not present.

Docs

https://godoc.org/github.com/anz-bank/decimal

Why decimal?

Binary floating point numbers are fundamentally flawed when it comes to representing exact numbers in a decimal world. Just like 1/3 can't be represented in base 10 (it evaluates to 0.3333333333 repeating), 1/10 can't be represented in binary. The solution is to use a decimal floating point number. Binary floating point numbers (often just called floating point numbers) are usually in the form Sign * Significand * 2 ^ exp and decimal floating point numbers change this to Sign * Significand * 10 ^ exp. The use of base 10 eliminates the decimal fraction problem.

Why fixed precision?

Most implementations of a decimal floating point datatype implement an arbitrary precision type, which often uses an underlying big int. This gives flexibility in that as the number grows, the number of bits assigned to the number grows ( hence the term "arbitrary precision"). This library is different. It uses a 64-bit decimal datatype as specified in the IEEE-754R standard. This sacrifices the ability to represent arbitrarily large numbers, but is much faster than arbitrary precision libraries. There are two main reasons for this:

  1. The fixed-size data type is a uint64 under the hood and never requires heap allocation.
  2. All the algorithms can hard-code assumptions about the number of bits to work with. In fact, many of the operations work on the entire number as a single unit using 64-bit integer arithmetic and, on the occasions it needs to use more, 128 bits always suffices.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultContext64 = Context64{Rounding: HalfUp}

DefaultContext64 is the context that arithmetic functions will use in order to do calculations. Setting this context to a different value will globally affect all Decimal64 methods whose behavior depends on context. Note that all such methods are also available as direct methods of Context64. It uses HalfUp rounding.

View Source
var DefaultFormatContext64 = Context64{Rounding: HalfEven}

DefaultFormatContext64 is the default context use for formatting Decimal64. Unlike DefaultContext64, it uses HalfEven rounding to conform to standard Go formatting for float types.

View Source
var DefaultScanContext64 = DefaultFormatContext64
View Source
var E64 = newFromParts(0, -15, 2_718281828459045)

E64 represents the transcendental number e (lim[n→∞](1+1/n)ⁿ).

View Source
var ErrNaN64 error = Error("sNaN64")
View Source
var Infinity64 = new64(inf64)

Infinity64 is ∞ represented as a Decimal64.

View Source
var Max64 = newFromParts(0, expMax, maxSig)

Max64 is the highest finite number representable as a Decimal64. It has the value 9.999999999999999E+384.

View Source
var Min64 = newFromParts(0, -398, 1)

Min64 is the closest positive number to zero. It has the value 1E-398.

View Source
var NegInfinity64 = new64(neg64 | inf64)

NegInfinity64 is -∞ represented as a Decimal64.

View Source
var NegMax64 = newFromParts(1, expMax, maxSig)

NegMax64 is the lowest finite number representable as a Decimal64. It has the value -9.999999999999999E+384.

View Source
var NegMin64 = newFromParts(1, -398, 1)

Min64 is the closest negative number to zero. It has the value -1E-398.

View Source
var NegOne64 = newFromParts(1, -15, decimal64Base)

NegOne64 is -1 represented as a Decimal64.

View Source
var NegZero64 = newFromParts(1, 0, 0)

NegZero64 is -0 represented as a Decimal64. Note that Zero64 != NegZero64, but Zero64.Equal(NegZero64) returns true.

View Source
var One64 = newFromParts(0, -15, decimal64Base)

One64 is 1 represented as a Decimal64.

View Source
var Pi64 = newFromParts(0, -15, 3_141592653589793)

Pi64 represents the transcendental number π.

View Source
var QNaN64 = new64(0x7c << 56)

QNaN64 a quiet NaN represented as a Decimal64.

View Source
var SNaN64 = new64(0x7e << 56)

SNaN64 a signalling NaN represented as a Decimal64. Note that the decimal never signals on NaNs but some operations treat sNaN differently to NaN.

View Source
var Zero64 = newFromParts(0, 0, 0)

Zero64 is 0 represented as a Decimal64.

Functions

This section is empty.

Types

type Context64

type Context64 struct {
	// Rounding sets the rounding behaviour of arithmetic operations.
	Rounding Rounding
}

Context64 may be used to tune the behaviour of arithmetic operations.

func (Context64) Add

func (ctx Context64) Add(d, e Decimal64) Decimal64

Add computes d + e

func (Context64) FMA

func (ctx Context64) FMA(d, e, f Decimal64) Decimal64

FMA computes d*e + f

func (Context64) Mul

func (ctx Context64) Mul(d, e Decimal64) Decimal64

Mul computes d * e

func (Context64) MustParse added in v1.6.0

func (ctx Context64) MustParse(s string) Decimal64

MustParse64 parses a string as a Decimal64 and returns the value or panics if the string doesn't represent a valid Decimal64.

func (Context64) Parse added in v1.6.0

func (ctx Context64) Parse(s string) (Decimal64, error)

Parse64 parses a string representation of a number as a Decimal64.

func (Context64) Quo

func (ctx Context64) Quo(d, e Decimal64) Decimal64

Quo computes d / e. Rounding rules are applied as per the context.

func (Context64) Round added in v1.4.0

func (ctx Context64) Round(d, e Decimal64) Decimal64

Round rounds a number to a given power of ten value. The e argument should be a power of ten, such as 1, 10, 100, 1000, etc.

func (Context64) Scan added in v1.6.0

func (ctx Context64) Scan(d *Decimal64, state fmt.ScanState, verb rune) error

Scan scans a string into a Decimal64, applying context rounding.

func (Context64) Sub added in v1.5.0

func (ctx Context64) Sub(d, e Decimal64) Decimal64

Add computes d + e

func (Context64) ToIntegral added in v1.4.0

func (ctx Context64) ToIntegral(d Decimal64) Decimal64

ToIntegral rounds d to a nearby integer.

func (Context64) With added in v1.6.0

func (ctx Context64) With(d Decimal64) Contextual

type Contextual added in v1.6.0

type Contextual struct {
	// contains filtered or unexported fields
}

Contextual binds a Decimal64 to a Context64 for greater control of formatting. It implements fmt.Stringer and fmt.Formatter on behalf of the number, using the context to control formatting.

func (Contextual) Format added in v1.6.0

func (c Contextual) Format(s fmt.State, verb rune)

func (Contextual) String added in v1.6.0

func (c Contextual) String() string

func (Contextual) Text added in v1.6.0

func (c Contextual) Text(verb rune, width, prec int) string

type Decimal64

type Decimal64 struct {
	// contains filtered or unexported fields
}

Decimal64 represents an IEEE 754 64-bit floating point decimal number. It uses the binary representation method. Decimal64 is intentionally a struct to ensure users don't accidentally cast it to uint64.

func MustParse64

func MustParse64(s string) Decimal64

MustParse64 parses a string as a Decimal64 and returns the value or panics if the string doesn't represent a valid Decimal64. It uses DefaultScanContext64.

func New64FromInt64

func New64FromInt64(i int64) Decimal64

New64FromInt64 returns a new Decimal64 with the given value.

func Parse64

func Parse64(s string) (Decimal64, error)

Parse64 parses a string representation of a number as a Decimal64. It uses DefaultScanContext64.

func (Decimal64) Abs

func (d Decimal64) Abs() Decimal64

Abs computes ||d||.

func (Decimal64) Add

func (d Decimal64) Add(e Decimal64) Decimal64

Add computes d + e. It uses DefaultContext64 to call Context64.Add.

func (Decimal64) Append

func (d Decimal64) Append(buf []byte, format byte, prec int) []byte

Append appends the text representation of d to buf.

func (Decimal64) Class

func (d Decimal64) Class() string

Class returns a string representing the number's 'type' that the decimal is. It can be one of the following:

  • "+Normal"
  • "-Normal"
  • "+Subnormal"
  • "-Subnormal"
  • "+Zero"
  • "-Zero"
  • "+Infinity"
  • "-Infinity"
  • "NaN"
  • "sNaN"

func (Decimal64) Cmp

func (d Decimal64) Cmp(e Decimal64) int

Cmp returns:

-2 if d or e is NaN
-1 if d <  e
 0 if d == e (incl. -0 == 0, -Inf == -Inf, and +Inf == +Inf)
+1 if d >  e

func (Decimal64) Cmp64 added in v1.2.0

func (d Decimal64) Cmp64(e Decimal64) Decimal64

Cmp64 returns the same output as Cmp as a Decimal64, unless d or e is NaN, in which case it returns a corresponding NaN result.

func (Decimal64) CopySign added in v1.2.0

func (d Decimal64) CopySign(e Decimal64) Decimal64

CopySign copies d, but with the sign taken from e.

func (Decimal64) Equal added in v1.5.0

func (d Decimal64) Equal(e Decimal64) bool

Equal indicates whether two numbers are equal. It is equivalent to d.Cmp(e) == 0.

func (Decimal64) FMA

func (d Decimal64) FMA(e, f Decimal64) Decimal64

FMA computes d × e + f. It uses DefaultContext64 to call Context64.FMA.

func (Decimal64) Float64

func (d Decimal64) Float64() float64

Float64 returns a float64 representation of d.

func (Decimal64) Format

func (d Decimal64) Format(s fmt.State, verb rune)

Format implements fmt.Formatter.

func (*Decimal64) GobDecode

func (d *Decimal64) GobDecode(buf []byte) error

GobDecode implements encoding.GobDecoder.

func (Decimal64) GobEncode

func (d Decimal64) GobEncode() ([]byte, error)

GobEncode implements encoding.GobEncoder.

func (Decimal64) Int64

func (d Decimal64) Int64() int64

Int64 returns an int64 representation of d, clamped to [math.MinInt64, math.MaxInt64].

func (Decimal64) Int64x added in v1.8.0

func (d Decimal64) Int64x() (i int64, exact bool)

Int64 returns an int64 representation of d, clamped to [math.MinInt64, math.MaxInt64]. The second return value, exact indicates whether New64FromInt64(i) == d.

func (Decimal64) IsInf

func (d Decimal64) IsInf() bool

IsInf indicates whether d is ±∞.

func (Decimal64) IsInt

func (d Decimal64) IsInt() bool

IsInt indicates whether d is an integer.

func (Decimal64) IsNaN

func (d Decimal64) IsNaN() bool

IsNaN indicates whether d is not a number.

func (Decimal64) IsQNaN

func (d Decimal64) IsQNaN() bool

IsQNaN indicates whether d is a quiet NaN.

func (Decimal64) IsSNaN

func (d Decimal64) IsSNaN() bool

IsSNaN indicates whether d is a signalling NaN.

func (Decimal64) IsSubnormal

func (d Decimal64) IsSubnormal() bool

IsSubnormal indicates whether d is a subnormal.

func (Decimal64) IsZero

func (d Decimal64) IsZero() bool

IsZero returns true if the Decimal encodes a zero value.

func (Decimal64) Logb added in v1.2.0

func (d Decimal64) Logb() Decimal64

Logb return the integral log10 of d.

func (Decimal64) MarshalBinary added in v1.2.0

func (d Decimal64) MarshalBinary() ([]byte, error)

MarshalBinary implements the encoding.BinaryMarshaler interface.

func (Decimal64) MarshalJSON

func (d Decimal64) MarshalJSON() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (Decimal64) MarshalText

func (d Decimal64) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (Decimal64) Max added in v1.2.0

func (d Decimal64) Max(e Decimal64) Decimal64

Max returns the lower of d and e.

func (Decimal64) MaxMag added in v1.2.0

func (d Decimal64) MaxMag(e Decimal64) Decimal64

MaxMag returns the lower of d and e.

func (Decimal64) Min added in v1.2.0

func (d Decimal64) Min(e Decimal64) Decimal64

Min returns the lower of d and e.

func (Decimal64) MinMag added in v1.2.0

func (d Decimal64) MinMag(e Decimal64) Decimal64

MinMag returns the lower of d and e.

func (Decimal64) Mul

func (d Decimal64) Mul(e Decimal64) Decimal64

Mul computes d × e. It uses DefaultContext64 to call Context64.Mul.

func (Decimal64) Neg

func (d Decimal64) Neg() Decimal64

Neg computes -d.

func (Decimal64) NextMinus added in v1.2.0

func (d Decimal64) NextMinus() Decimal64

NextMinus returns the next value above d.

func (Decimal64) NextPlus added in v1.2.0

func (d Decimal64) NextPlus() Decimal64

NextPlus returns the next value above d.

func (Decimal64) Quo

func (d Decimal64) Quo(e Decimal64) Decimal64

Quo computes d ÷ e. It uses DefaultContext64 to call Context64.Quo.

func (Decimal64) Round added in v1.4.0

func (d Decimal64) Round(e Decimal64) Decimal64

Round rounds a number to a given power-of-10 value. The e argument should be a power of ten, such as 1, 10, 100, 1000, etc. It uses DefaultContext64 to call Context64.Round.

func (Decimal64) ScaleB added in v1.8.0

func (d Decimal64) ScaleB(e Decimal64) Decimal64

func (Decimal64) ScaleBInt added in v1.8.0

func (d Decimal64) ScaleBInt(i int) Decimal64

func (*Decimal64) Scan

func (d *Decimal64) Scan(state fmt.ScanState, verb rune) error

Scan implements fmt.Scanner. It uses DefaultScanContext64.

func (Decimal64) Sign

func (d Decimal64) Sign() int

Sign returns -1/0/1 if d is </=/> 0, respectively.

func (Decimal64) Signbit

func (d Decimal64) Signbit() bool

Signbit indicates whether d is negative or -0.

func (Decimal64) Sqrt

func (d Decimal64) Sqrt() Decimal64

Sqrt computes √d.

func (Decimal64) String

func (d Decimal64) String() string

String returns a string representation of d.

func (Decimal64) Sub

func (d Decimal64) Sub(e Decimal64) Decimal64

Sub returns d - e. It uses DefaultContext64 to call Context64.Sub.

func (Decimal64) Text

func (d Decimal64) Text(format byte, prec int) string

Text converts the floating-point number x to a string according to the given format and precision prec.

func (Decimal64) ToIntegral added in v1.4.0

func (d Decimal64) ToIntegral() Decimal64

ToIntegral rounds d to a nearby integer. It uses DefaultContext64 to call Context64.ToIntegral.

func (*Decimal64) UnmarshalBinary added in v1.2.0

func (d *Decimal64) UnmarshalBinary(data []byte) error

UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.

func (*Decimal64) UnmarshalJSON

func (d *Decimal64) UnmarshalJSON(data []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (*Decimal64) UnmarshalText

func (d *Decimal64) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type Error added in v1.9.0

type Error string

func (Error) Error added in v1.9.0

func (e Error) Error() string

type Rounding added in v1.5.0

type Rounding int

Rounding defines how arithmetic operations round numbers in certain operations.

const (
	// HalfUp rounds to the nearest number, rounding away from zero if the
	// number is exactly halfway between two possible roundings.
	HalfUp Rounding = iota

	// HalfEven rounds to the nearest number, rounding to the nearest even
	// number if the number is exactly halfway between two possible roundings.
	HalfEven

	// Down rounds towards zero.
	Down
)

func (Rounding) String added in v1.6.0

func (r Rounding) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL