decimal

package module
v2.0.0-...-db694ce Latest Latest
Warning

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

Go to latest
Published: Oct 14, 2017 License: BSD-3-Clause Imports: 16 Imported by: 0

README

decimal Build Status GoDoc

Decimal is a high-performance, arbitrary precision, fixed-point decimal library implementing the General Decimal Arithmetic specification.

Features

  • Zero-values are safe to use without initialization.
  • Multiple operating modes (GDA, Go) to fit your use cases.
  • High performance.
  • A math library with sqrt, exp, log, continued fractions, and more.
  • A familiar, idiomatic API.

Installation

go get github.com/ericlagergren/decimal

Documentation

http://godoc.org/github.com/ericlagergren/decimal

License

The BSD 3-clause

Documentation

Overview

Package decimal provides a high-performance, arbitrary precision, fixed-point decimal library.

The following type is supported:

Big decimal numbers

The zero value for a Big corresponds with 0. Its method naming is the same as math/big's, meaning:

func (z *T) SetV(v V) *T          // z = v
func (z *T) Unary(x *T) *T        // z = unary x
func (z *T) Binary(x, y *T) *T    // z = x binary y
func (x *T) Pred() P              // p = pred(x)

In general, its conventions will mirror math/big's.

In general, operations that use the receiver z as storage will not modify z's Context. Additionally, the arguments to Binary and Unary methods are allowed to alias, so the following is valid:

x := New(1, 0)
x.Add(x, x) // x == 2

Compared to other decimal libraries, this package:

  1. Has signals and traps, but only if you want them
  2. Only has mutable decimals (for efficiency's sake)

Index

Examples

Constants

View Source
const (
	MaxScale = math.MaxInt32 // largest allowed scale.
	MinScale = math.MinInt32 // smallest allowed scale.

	MaxPrecision = math.MaxInt32 // largest allowed Context precision.
	MinPrecision = 1             // smallest allowed Context precision.
)

Precision and scale limits.

View Source
const DefaultPrecision = 16

DefaultPrecision is the default precision used for decimals created as literals or using new.

Variables

View Source
var (
	// Context32 is the IEEE 754R Decimal32 format.
	Context32 = Context{

		RoundingMode:  ToNearestEven,
		OperatingMode: GDA,
		Traps:         ^(Inexact | Rounded | Subnormal),
		// contains filtered or unexported fields
	}

	// Context64 is the IEEE 754R Decimal64 format.
	Context64 = Context{

		RoundingMode:  ToNearestEven,
		OperatingMode: GDA,
		Traps:         ^(Inexact | Rounded | Subnormal),
		// contains filtered or unexported fields
	}

	// Context128 is the IEEE 754R Decimal128 format.
	Context128 = Context{

		RoundingMode:  ToNearestEven,
		OperatingMode: GDA,
		Traps:         ^(Inexact | Rounded | Subnormal),
		// contains filtered or unexported fields
	}
)

The following Contexts are based on IEEE 754R. Context is exported for this documentation but is not expected to be used itself. Each Context's RoundingMode is ToNearestEven, OperatingMode is GDA, and traps are set to every exception other than Inexact, Rounded, and Subnormal.

View Source
var Regexp = regexp.MustCompile(`(?i)(((\+|-)?(\d+\.\d*|\.?\d+)([eE][+-]?\d+)?)|(inf(infinity)?))|((\+|-)?([sq]?nan))`)

Regexp matches any valid string representing a decimal that can be pased to SetString.

Functions

func Raw

func Raw(x *Big) (int64, *big.Int)

Raw directly returns x's raw compact and unscaled values. Caveat emptor: Neither are guaranteed to be valid. Raw is intended to support missing functionality outside this package and generally should be avoided. Additionally, Raw is the only part of this package's API which is not guaranteed to remain stable. This means the function could change or disappear at any time, even across minor version numbers.

Types

type Big

type Big struct {

	// Context is the decimal's unique contextual object.
	Context Context
	// contains filtered or unexported fields
}

Big is a fixed-point, arbitrary-precision decimal number.

A Big decimal is a number and a scale, the latter representing the number of digits following the radix if the scale is >= 0. Otherwise, it's the number * 10 ^ -scale.

Example (ReversePolishNotationCalculator)
const input = "15 7 1 1 + - / 3 * 2 1 1 + + - 5 * 3 / ="
var stack []*Big
for _, tok := range strings.Split(input, " ") {
	last := len(stack) - 1
	switch tok {
	case "+":
		x := stack[last-1]
		x.Add(x, stack[last])
		stack = stack[:last]
	case "-":
		x := stack[last-1]
		x.Sub(x, stack[last])
		stack = stack[:last]
	case "/":
		x := stack[last-1]
		x.Quo(x, stack[last])
		stack = stack[:last]
	case "*":
		x := stack[last-1]
		x.Mul(x, stack[last])
		stack = stack[:last]
	case "=":
		break
	default:
		x := new(Big)
		x.Context = Context128
		if _, ok := x.SetString(tok); !ok {
			fmt.Fprintf(os.Stderr, "invalid decimal: %v\n", x.Context.Err)
			os.Exit(1)
		}
		stack = append(stack, x)
	}
}
fmt.Printf("%+6.4g\n", stack[0])
Output:

+8.333

func New

func New(value int64, scale int32) *Big

New creates a new Big decimal with the given value and scale. For example:

New(1234, 3) // 1.234
New(42, 0)   // 42
New(4321, 5) // 0.04321
New(-1, 0)   // -1
New(3, -10)  // 30 000 000 000

func (*Big) Abs

func (z *Big) Abs(x *Big) *Big

Abs sets z to the absolute value of x and returns z.

func (*Big) Add

func (z *Big) Add(x, y *Big) *Big

Add sets z to x + y and returns z.

func (*Big) BitLen

func (x *Big) BitLen() int

BitLen returns the absolute value of x in bits. The result is undefined if x is an infinity or not a number value.

func (*Big) Cmp

func (z *Big) Cmp(x *Big) int

Cmp compares d and x and returns:

-1 if z <  x
 0 if z == x
+1 if z >  x

It does not modify z or x. The result is undefined if either z or x are not a number values.

func (*Big) Copy

func (z *Big) Copy(x *Big) *Big

Copy sets z to a copy of x and returns z.

func (*Big) Float64

func (x *Big) Float64() float64

Float64 returns x as a float64.

func (*Big) Format

func (x *Big) Format(s fmt.State, c rune)

Format implements the fmt.Formatter interface. The following verbs are supported:

%s: -dddd.dd or -d.dddd±edd, depending on x
%d: same as %s
%v: same as %s
%e: -d.dddd±edd
%E: -d.dddd±Edd
%f: -dddd.dd
%g: same as %f

Precision and width are honored in the same manner as the fmt package. In short, width is the minimum width of the formatted number. Given %f, precision is the number of digits following the radix. Given %g, precision is the number of significant digits.

Format honors all flags (such as '+' and ' ') in the same manner as the fmt package, except for '#'. Unless used in conjunction with %v, %q, or %p, the '#' flag will be ignored; decimals have no defined hexadeximal or octal representation.

%+v, %#v, %T, %#p, and %p all honor the formats specified in the fmt package's documentation.

func (*Big) Int

func (x *Big) Int() *big.Int

Int returns x as a big.Int, truncating the fractional portion, if any. If x is an infinity or a not a number value the result is undefined.

func (*Big) Int64

func (x *Big) Int64() int64

Int64 returns x as an int64, truncating the fractional portion, if any. The result is undefined if x is an infinity, a not a number value, or if x does not fit inside an int64.

func (*Big) IsBig

func (x *Big) IsBig() bool

IsBig returns true if x, with its fractional part truncated, cannot fit inside an int64. If x is an infinity or a not a number value the result is undefined.

func (*Big) IsFinite

func (x *Big) IsFinite() bool

IsFinite returns true if x is finite.

func (*Big) IsInf

func (x *Big) IsInf(sign int) bool

IsInf returns true if x is an infinity according to sign. If sign > 0, IsInf reports whether x is positive infinity. If sign < 0, IsInf reports whether x is negative infinity. If sign == 0, IsInf reports whether x is either infinity.

func (*Big) IsInt

func (x *Big) IsInt() bool

IsInt reports whether x is an integer. Inf and NaN values are not integers.

func (*Big) IsNaN

func (x *Big) IsNaN(signal int) bool

IsNaN returns true if x is NaN. If sign > 0, IsNaN reports whether x is signaling NaN. If sign < 0, IsNaN reports whether x is quiet NaN. If sign == 0, IsNaN reports whether x is either NaN.

func (*Big) MarshalText

func (x *Big) MarshalText() ([]byte, error)

MarshalText implements encoding/TextMarshaler.

func (*Big) Mul

func (z *Big) Mul(x, y *Big) *Big

Mul sets z to x * y and returns z.

func (*Big) Neg

func (z *Big) Neg(x *Big) *Big

Neg sets z to -x and returns z. If x is positive infinity, z will be set to negative infinity and visa versa. If x == 0, z will be set to zero as well. NaN has no negative representation, and will result in an error.

func (*Big) Precision

func (x *Big) Precision() int

Precision returns the precision of x. That is, it returns the number of digits in the unscaled form of x. x == 0 has a precision of 1. The result is undefined if x is an infinity or a not a number value.

Example
a := New(12, 0)
b := New(42, -2)
c := New(12345, 3)
d := New(3, 5)

fmt.Printf(`
%s has a precision of %d
%s has a precision of %d
%s has a precision of %d
%s has a precision of %d
`, a, a.Precision(), b, b.Precision(), c, c.Precision(), d, d.Precision())
Output:


12 has a precision of 2
4.2e+3 has a precision of 2
12.345 has a precision of 5
0.00003 has a precision of 1

func (*Big) Quo

func (z *Big) Quo(x, y *Big) *Big

Quo sets z to x / y and returns z.

func (*Big) Round

func (z *Big) Round(n int32) *Big

Round rounds z down to n digits of precision and returns z. The result is undefined if n < 0 or z is not finite. No rounding will occur if n == 0. The result of Round will always be within the interval [⌊z⌋, z].

Example
a := New(1234, 0).Round(2)
b := New(544, 1).Round(2)
c := New(60, 0).Round(5)

fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
Output:

1.2e+3
54
60

func (*Big) Scale

func (x *Big) Scale() int32

Scale returns x's scale.

func (*Big) Set

func (z *Big) Set(x *Big) *Big

Set sets z to x and returns z. The result might be rounded depending on z's Context.

func (*Big) SetBigMantScale

func (z *Big) SetBigMantScale(value *big.Int, scale int32) *Big

SetBigMantScale sets z to the given value and scale.

func (*Big) SetFloat64

func (z *Big) SetFloat64(value float64) *Big

SetFloat64 sets z to the provided float64.

Because certain numbers cannot be exactly represented as floating-point numbers, SetFloat64 "rounds" its input in order to break it into simple mantissa and scale parts as if SetMantScale were called. If SetFloat64 took its input as-is, the result of calling SetFloat64(0.1) would be 0.1000000000000000055511151231257827021181583404541015625.

Approximately 2.3% of decimals created from floats will have an rounding imprecision of ± 1 ULP.

func (*Big) SetInf

func (x *Big) SetInf(signbit bool) *Big

SetInf sets x to -Inf if signbit is set or +Inf is signbit is not set, and returns x.

func (*Big) SetMantScale

func (z *Big) SetMantScale(value int64, scale int32) *Big

SetMantScale sets z to the given value and scale.

func (*Big) SetNaN

func (z *Big) SetNaN(signal bool) *Big

SetNaN sets z to a signaling NaN if signal is true or quiet NaN otherwise and returns z.

func (*Big) SetScale

func (z *Big) SetScale(scale int32) *Big

SetScale sets z's scale to scale and returns z.

func (*Big) SetString

func (z *Big) SetString(s string) (*Big, bool)

SetString sets z to the value of s, returning z and a bool indicating success. s must be a string in one of the following formats:

1.234
1234
1.234e+5
1.234E-5
0.000001234
Inf
+Inf
-Inf
NaN
qNaN
sNaN

Inf and NaN map to +Inf and qNaN, respectively. NaN values may have optional diagnostic information, represented as trailing digits; for example, “NaN123”. These digits are otherwise ignored but are included for robustness.

func (*Big) Sign

func (x *Big) Sign() int

Sign returns:

-1 if x <  0
 0 if x == 0
+1 if x >  0

The result is undefined if x is a not a number value.

func (*Big) Signbit

func (x *Big) Signbit() bool

Signbit returns true if x is negative, negative infinity, or negative zero.

func (*Big) String

func (x *Big) String() string

String returns the string representation of x. It's equivalent to the %s verb discussed in the Format method's documentation. Special cases depend on the OperatingMode. The defaults (for OperatingMode == Go) are:

"<nil>" if x == nil
"+Inf"  if x.IsInf(+1)
"+Inf"  if x.IsInf(0)
"-Inf"  if x.IsInf(-1)

func (*Big) Sub

func (z *Big) Sub(x, y *Big) *Big

Sub sets z to x - y and returns z.

func (*Big) UnmarshalText

func (z *Big) UnmarshalText(data []byte) error

UnmarshalText implements encoding/TextUnmarshaler.

type Condition

type Condition uint32

Condition is a bitmask value raised after or during specific operations. For example, dividing by zero is undefined so a DivisionByZero Condition flag will be set in the decimal's Context.

const (
	// Clamped occurs if the scale has been modified to fit the constraints of
	// the decimal representation.
	Clamped Condition = 1 << iota
	// ConversionSyntax occurs when a string is converted to a decimal and does
	// not have a valid syntax.
	ConversionSyntax
	// DivisionByZero occurs when division is attempted with a finite,
	// non-zero dividend and a divisor with a value of zero.
	DivisionByZero
	// DivisionImpossible occurs when the result of integer division would
	// contain too many digits (i.e. be longer than the specified precision).
	DivisionImpossible
	// DivisionUndefined occurs when division is attempted with in which both
	// the divided and divisor are zero.
	DivisionUndefined
	// Inexact occurs when the result of an operation (e.g. division) is not
	// exact, or when the Overflow/Underflow Conditions occur.
	Inexact
	// InsufficientStorage occurs when the system doesn't have enough storage
	// (i.e. memory) to store the decimal.
	InsufficientStorage
	// InvalidContext occurs when an invalid context was detected during an
	// operation. This might occur if, for example, an invalid RoundingMode was
	// passed to a Context.
	InvalidContext
	// InvalidOperation occurs when:
	//
	// 	- an operand to an operation is a signaling NaN
	// 	- an attempt is made to add or subtract infinities of opposite signs
	// 	- an attempt is made to multiply zero by an infinity of either sign
	// 	- an attempt is made to divide an infinity by an infinity
	// 	- the divisor for a remainder operation is zero
	// 	- the dividend for a remainder operation is an infinity
	// 	- either operand of the quantize operation is an infinity, or the result
	// 	  of a quantize operation would require greater precision than is
	// 	  available
	// 	- the operand of the ln or the log10 operation is less than zero
	// 	- the operand of the square-root operation has a sign of 1 and a
	// 	  non-zero coefficient
	// 	- both operands of the power operation are zero, or if the left-hand
	// 	  operand is less than zero and the right-hand operand does not have an
	// 	  integral value or is an infinity
	//
	InvalidOperation
	// Overflow occurs when the adjusted scale, after rounding, would be
	// greater than MaxScale. (Inexact and Rounded will also be raised.)
	Overflow
	// Rounded occurs when the result of an operation is rounded, or if an
	// Overflow/Underflow occurs.
	Rounded
	// Subnormal ocurs when the result of a conversion or operation is subnormal
	// (i.e. the adjusted scale is less than MinScale before any rounding).
	Subnormal
	// Underflow occurs when the result is inexact and the adjusted scale would
	// be smaller (more negative) than MinScale.
	Underflow
)

func (Condition) String

func (c Condition) String() string

type Context

type Context struct {
	// OperatingMode which dictates how the decimal operates. For example, the
	// Decimal Arithmetic Specification (version 1.70) requires an infinity
	// decimal, to return "Infinity" from its "String" (or equivalent) method.
	// This, however, differs from other Go types like float64 and big.Float
	// that return "+Inf" or "-Inf." To compensate, Context provides multiple
	// modes that so the client can choose a preferred mode.
	OperatingMode OperatingMode

	// Traps are a set of exceptional conditions that should result in an error.
	Traps Condition

	// Conditions are a set of the most recent exceptional conditions to occur
	// during an operation.
	Conditions Condition

	// Err is the most recent error to occur during an operation.
	Err error

	// RoundingMode instructs how an infinite (repeating) decimal expansion
	// (digits following the radix) should be rounded. This can occur during
	// "lossy" operations like division.
	RoundingMode RoundingMode
	// contains filtered or unexported fields
}

Context is a per-decimal contextual object that governs specific operations such as how lossy operations (e.g. division) round.

func (Context) New

func (c Context) New(value int64, scale int32) *Big

New is shorthand to create a Big from a Context.

func (Context) Precision

func (c Context) Precision() int32

Precision returns the Context's precision.

func (*Context) SetPrecision

func (c *Context) SetPrecision(prec int32)

SetPrecision sets c's precision.

type ErrNaN

type ErrNaN struct {
	// TODO(eric): Perhaps use math/big.ErrNaN if possible in the future?
	Msg string
}

An ErrNaN panic is raised by a decimal operation that would lead to a NaN under IEEE-754 rules. An ErrNaN implements the error interface.

func (ErrNaN) Error

func (e ErrNaN) Error() string

type OperatingMode

type OperatingMode uint8

OperatingMode dictates how the decimal approaches specific non-numeric operations like conversions to strings and panicking on NaNs. See Context's documentation for further information.

const (
	// Go adheres to typical Go idioms.
	Go OperatingMode = iota
	// GDA strictly adheres to the General Decimal Arithmetic Specification
	// Version 1.70.
	GDA
)

func (OperatingMode) String

func (i OperatingMode) String() string

type RoundingMode

type RoundingMode uint8

RoundingMode determines how a decimal will be rounded if the exact result cannot accurately be represented.

const (
	ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
	ToNearestAway                     // == IEEE 754-2008 roundTiesToAway
	ToZero                            // == IEEE 754-2008 roundTowardZero
	AwayFromZero                      // no IEEE 754-2008 equivalent
	ToNegativeInf                     // == IEEE 754-2008 roundTowardNegative
	ToPositiveInf                     // == IEEE 754-2008 roundTowardPositive

	// Unneeded means finite decimal expansion. Lossy routines will panic if
	// this RoundingMode is provided and the lossy operation does not have a
	// finite decimal expansion.
	Unneeded
)

The following rounding modes are supported.

func (RoundingMode) String

func (i RoundingMode) String() string

Directories

Path Synopsis
internal
arith
Package arith provides simple, primarily bit-specific, arithmetic operations.
Package arith provides simple, primarily bit-specific, arithmetic operations.
arith/checked
Package checked implements basic checked arithmetic.
Package checked implements basic checked arithmetic.
arith/pow
Package pow implements basic power functions.
Package pow implements basic power functions.
c
Package c provides basic, internal constants.
Package c provides basic, internal constants.
Package math implements various useful mathematical functions and constants.
Package math implements various useful mathematical functions and constants.
sql
postgres
Package postgres provides a simple wrapper around a decimal.Big type, allowing it to be used in PostgreSQL queries.
Package postgres provides a simple wrapper around a decimal.Big type, allowing it to be used in PostgreSQL queries.
Package suite provides a simple API for parsing and using IBM Labs' "Floating-Point Test-Suite for IEEE"
Package suite provides a simple API for parsing and using IBM Labs' "Floating-Point Test-Suite for IEEE"

Jump to

Keyboard shortcuts

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