decimal

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2026 License: MIT Imports: 13 Imported by: 0

README

decimal

decimal is an immutable arbitrary-precision decimal type built on top of math/big.Int. It keeps both unscaled integer digits and decimal precision, making it suitable for financial and accounting workloads that require deterministic base-10 behavior.

Import path:

import "github.com/exc-works/decimal"

User Guides

Quick Start

package main

import (
	"fmt"

	"github.com/exc-works/decimal"
)

func main() {
	price := decimal.MustFromString("12.5000")
	fee := decimal.NewWithPrec(75, 2) // 0.75

	total := price.Add(fee)
	rounded := total.Rescale(2, decimal.RoundHalfEven)

	fmt.Println(price.String())                  // 12.5
	fmt.Println(price.StringWithTrailingZeros()) // 12.5000
	fmt.Println(total.String())                  // 13.25
	fmt.Println(rounded.String())                // 13.25
}

Common constants:

  • decimal.Zero
  • decimal.One
  • decimal.Ten
  • decimal.Hundred

Core Design

Decimal uses immutable value semantics:

  • methods like Add, Sub, Mul, Quo, and Rescale return new values
  • pointer receiver methods (Unmarshal*, Scan) update the receiver
  • BigInt() returns a copy, so internal state is not exposed for mutation

Example:

a := decimal.MustFromString("1.20")
b := a.Add(decimal.MustFromString("0.30"))

fmt.Println(a.String()) // 1.2  (a is unchanged)
fmt.Println(b.String()) // 1.5

Constructors

  • decimal.New(int64)
  • decimal.NewFromInt(int)
  • decimal.NewWithPrec(int64, prec)
  • decimal.NewFromFloat64(float64)
  • decimal.NewFromFloat32(float32)
  • decimal.NewWithAppendPrec(int64, prec)
  • decimal.NewFromUintWithAppendPrec(uint64, prec)
  • decimal.NewFromBigInt(*big.Int)
  • decimal.NewFromBigRat(*big.Rat)
  • decimal.NewFromBigRatWithPrec(*big.Rat, prec, decimal.RoundingMode)
  • decimal.NewFromBigIntWithPrec(*big.Int, prec)
  • decimal.NewFromInt64(int64, precision)
  • decimal.NewFromUint64(uint64, precision)
  • decimal.NewFromString(string)
  • decimal.MustFromString(string)
  • decimal.NewFromDecimal(Decimal) (deep copy)
  • d.Clone() (deep copy; useful after NewFromBigInt with an externally mutable *big.Int)
String Parsing

NewFromString supports:

  • plain decimals: 123, -123.45
  • scientific notation: 1.234e3, 123456E-3

It trims leading/trailing spaces and rejects malformed formats such as:

  • empty string
  • 1.
  • .1
  • multiple decimal points
  • missing or invalid exponent

If parsing results in zero, precision is normalized to 0.

Arithmetic and Rounding

Arithmetic
  • Add(Decimal) / SafeAdd(Decimal) / AddRaw(int64)
  • Sub(Decimal) / SafeSub(Decimal) / SubRaw(int64)
  • Mul(Decimal, decimal.RoundingMode)
  • MulDown(Decimal)
  • MulExact(Decimal) (exact multiplication, no rounding, precision = d.prec + d2.prec)
  • Mul2(Decimal) (deprecated alias of MulExact)
  • QuoWithPrec(Decimal, prec, decimal.RoundingMode)
  • Quo(Decimal, decimal.RoundingMode)
  • QuoDown(Decimal)
  • QuoRem(Decimal)
  • Mod(Decimal)
  • Power(int64)
  • Sqrt() (Decimal, error) / SqrtWithPrec(prec)
  • ApproxRoot(int64) (Decimal, error) / ApproxRootWithPrec(root, prec)
  • Log2() Decimal
  • Log10() (Decimal, error) / Log10WithPrec(prec) (input must be > 0)
  • Ln() (Decimal, error) / LnWithPrec(prec) (input must be > 0)
  • Exp() (Decimal, error) / ExpWithPrec(prec) (Taylor series with argument reduction)
Precision Utilities
  • RescaleDown(prec)
  • Rescale(prec, decimal.RoundingMode)
  • Shift(places)
  • TruncateWithPrec(prec) / RoundWithPrec(prec)
  • FloorWithPrec(prec) / CeilWithPrec(prec)
  • Truncate() / Round() / Floor() / Ceil()
  • StripTrailingZeros()
  • SignificantFigures(figures, decimal.RoundingMode)
Comparison
  • Cmp(Decimal)
  • Equal(Decimal) / NotEqual(Decimal)
  • GT(Decimal) / GTE(Decimal)
  • LT(Decimal) / LTE(Decimal)
  • Max(Decimal) / Min(Decimal)
  • package-level helpers: decimal.Max, decimal.Min, decimal.Between
Other Methods
  • IntPart()
  • Remainder()
  • Sign() / IsNegative() / IsZero() / IsNotZero() / IsPositive()
  • IsInteger() / HasFraction()
  • Neg() / Abs()
  • BigInt() / BigRat()
  • Float32() (float32, bool) / Float64() (float64, bool)
  • Int64() (int64, bool) / Uint64() (uint64, bool)
  • BitLen()
  • Precision()
  • MustNonNegative()
Rounding Modes
  • decimal.RoundDown (toward zero)
  • decimal.RoundUp (away from zero)
  • decimal.RoundCeiling (toward +infinity)
  • decimal.RoundHalfUp
  • decimal.RoundHalfDown
  • decimal.RoundHalfEven (banker's rounding)
  • decimal.RoundUnnecessary (panics if rounding is required)

Serialization

String
  • String() strips trailing zeros
  • StringWithTrailingZeros() keeps trailing zeros
  • FormatWithSeparators(thousands, decimal rune) for locale-aware display (e.g., 12345.67"12,345.67" or European "12.345,67")
  • Format(fmt.State, verb rune) implements fmt.Formatter, supporting %v, %s, %q, %d, %f, %e, %g, %b with width/precision/flags
JSON
  • MarshalJSON() encodes as a JSON string
  • UnmarshalJSON() accepts JSON string and (in some paths) raw JSON number text
  • uninitialized value marshals as null
XML
  • MarshalXML() / UnmarshalXML()
  • MarshalXMLAttr() / UnmarshalXMLAttr() for use in XML attributes
  • Uninitialized values encode as empty element/attribute
BSON
  • MarshalBSONValue() / UnmarshalBSONValue() via go.mongodb.org/mongo-driver/v2/bson
  • Encodes as BSON string; uninitialized encodes as BSON null
  • Decodes from String, Double, Int32, Int64, Decimal128, Null
  • NullDecimal also implements BSON value marshaling
YAML
  • MarshalYAML() returns string form
  • UnmarshalYAML() parses scalar string/number values
Text
  • MarshalText()
  • UnmarshalText()
  • UnmarshalParam(string) (for gin BindUnmarshaler)
Gin
  • ShouldBindQuery / ShouldBind / ShouldBindUri use UnmarshalParam(string)
  • ShouldBindJSON uses UnmarshalJSON()

Example:

type Req struct {
	Amount decimal.Decimal `form:"amount" uri:"amount" json:"amount"`
}

var req Req
if err := c.ShouldBindQuery(&req); err != nil {
	// handle error
}
Validator
  • Use decimal_required to require Decimal field presence
  • Built-in omitempty can be used as usual
  • Decimal numeric comparison tags: decimal_eq, decimal_ne, decimal_gt, decimal_gte, decimal_lt, decimal_lte, decimal_between (tilde-separated bounds, e.g. decimal_between=1~100; min must be <= max)
  • Sign/zero tags (no param): decimal_positive, decimal_negative, decimal_nonzero
  • Precision tag: decimal_max_precision=N — max number of decimal places (scale), i.e. digits after the decimal point; not total significant digits. 123.45 has scale 2 and passes decimal_max_precision=2.
  • Uses exact Decimal comparison (Cmp), without Float64 conversion
  • Supports friendly error messages via translation helpers: RegisterGoPlaygroundValidatorTranslations, RegisterGoPlaygroundValidatorTranslationsWithMessages, and TranslateGoPlaygroundValidationErrors
  • Built-in translation locales (13): en, zh, zh_Hant, ja, ko, fr, es, de, pt, pt_BR, ru, ar, hi
  • Register once before any validation; calling RegisterGoPlaygroundValidator multiple times on the same *validator.Validate is idempotent — later calls simply overwrite the previously registered handlers.

Safety note. Validator tag parameters must be compile-time constants. Passing malformed parameters (non-numeric limits, unparseable decimal values, min > max for decimal_between, negative decimal_max_precision) causes panics at validation time — do not splice untrusted input into struct tags.

Example:

import (
	"github.com/exc-works/decimal"
	"github.com/go-playground/validator/v10"
)

type Req struct {
	Amount decimal.Decimal `validate:"decimal_required,decimal_eq=12.34"`
}

v := validator.New()
_ = decimal.RegisterGoPlaygroundValidator(v)
err := v.Struct(Req{Amount: decimal.MustFromString("12.34")})

Friendly messages example:

import (
	"github.com/go-playground/locales/en"
	ut "github.com/go-playground/universal-translator"
)

enLocale := en.New()
uni := ut.New(enLocale, enLocale)
trans, _ := uni.GetTranslator("en")

_ = decimal.RegisterGoPlaygroundValidatorTranslations(v, trans)
messages := decimal.TranslateGoPlaygroundValidationErrors(err, trans)

Custom language template override example:

_ = decimal.RegisterGoPlaygroundValidatorTranslationsWithMessages(v, trans, map[string]string{
	"decimal_required": "{0} cannot be empty",
})

For gin:

import (
	"github.com/exc-works/decimal"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)

if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
	_ = decimal.RegisterGoPlaygroundValidator(v)
}
Binary / protobuf
  • MarshalBinary() / UnmarshalBinary()
  • Marshal() / Unmarshal()
  • MarshalTo([]byte)
  • Size()

Binary format:

  • first 4 bytes: big-endian uint32 precision
  • remaining bytes: gob-encoded big.Int
  • trailing zeros are stripped before serialization
  • decimal.PrecisionFixedSize == 4
Database
  • Value() implements driver.Valuer
  • Scan(any) implements sql.Scanner

Scan supports: nil, float32, float64, int64, string, []byte, and quoted/unquoted decimal text.

NullDecimal

For nullable SQL columns, use NullDecimal:

type Row struct {
    Amount decimal.NullDecimal
}

var r Row
_ = db.QueryRow("SELECT amount FROM t").Scan(&r.Amount)
if r.Amount.Valid {
    fmt.Println(r.Amount.Decimal.String())
}

NullDecimal implements sql.Scanner, driver.Valuer, JSON/YAML/Text/BSON marshaling, and gin UnmarshalParam. null/empty input sets Valid=false.

Error Handling

The package exposes sentinel errors so callers can switch on error category via errors.Is:

  • ErrInvalidFormat — malformed decimal string in NewFromString, UnmarshalJSON, etc.
  • ErrInvalidPrecision — negative precision
  • ErrOverflow — int64/uint64/float conversion overflow
  • ErrDivideByZero — division by zero
  • ErrNegativeRoot — even root of a negative value (Sqrt, ApproxRoot)
  • ErrInvalidRoot — non-positive root passed to ApproxRoot
  • ErrInvalidLog — logarithm of a non-positive value
  • ErrRoundUnnecessary — rounding required under RoundUnnecessary mode
  • ErrUnmarshal — binary/YAML/BSON/SQL unmarshal failures
  • ErrInvalidArgument — invalid setup argument (e.g. nil validator/translator)
_, err := decimal.NewFromString("not a number")
if errors.Is(err, decimal.ErrInvalidFormat) {
    // handle
}

Concurrency

  • Decimal values are safe for concurrent read access by multiple goroutines as long as no goroutine reassigns the variable.
  • Value-receiver methods (Add, Sub, Mul, Cmp, String, etc.) never mutate the receiver and are safe to call concurrently.
  • Pointer-receiver methods (Scan, UnmarshalJSON, UnmarshalYAML, UnmarshalText, UnmarshalBinary) mutate the receiver; external synchronization is required when the same *Decimal may be accessed concurrently.
  • Accessors like BigInt() / BigRat() return defensive copies.
  • Package-level constants (Zero, One, Ten, Hundred) are read-only.

Notes and Pitfalls

  • negative precision panics in constructors/rescaling
  • NewFromString returns error; MustFromString panics
  • MustNonNegative panics for negative values
  • Log2() panics unless value > 0
  • ApproxRoot(root) requires root > 0
  • even root of negative values returns error
  • Quo has a special integer-division path when both precisions are 0
  • binary encoding normalizes trailing zeros (7.50 and 7.5000 can encode identically)

Migration Notes

If you are migrating from older internal variants of this library:

  • rely only on APIs present in this repository
  • update formatting-sensitive code if it depended on fixed-scale output (StringWithTrailingZeros)
  • validate binary compatibility if old code expected trailing-zero preservation

Release and Versioning

Example:

git tag -a v0.1.0 -m "release v0.1.0"
git push origin v0.1.0
BSON support (optional)

BSON support is compiled out by default so that downstream projects are not forced to pull in go.mongodb.org/mongo-driver/v2. To enable it, build with the bson build tag:

go build -tags bson ./...
go test  -tags bson ./...

When the tag is set, Decimal and NullDecimal implement bson.ValueMarshaler / bson.ValueUnmarshaler (see marshal_bson.go). Without the tag, no BSON code is compiled and the MongoDB driver is not linked into the resulting binary, keeping the core library dependency-free.

Documentation

Overview

Package decimal provides an immutable arbitrary-precision decimal type built on top of math/big.Int.

Decimal values keep both unscaled integer digits and decimal precision, which makes the package suitable for financial and accounting scenarios that require deterministic base-10 behavior.

Concurrency

A Decimal value is safe for concurrent read access by multiple goroutines provided that no goroutine reassigns the variable holding it. The type is designed around immutable semantics: arithmetic and inspection methods have value receivers (for example Add, Sub, Mul, Quo, Cmp, Sign, String, StringWithTrailingZeros, IntPart, Precision, IsZero, MarshalJSON, MarshalText, MarshalBinary) and return new Decimal values without mutating the receiver, so invoking them concurrently on the same Decimal is safe.

Methods with pointer receivers mutate the receiver and therefore require external synchronization whenever the same *Decimal may be accessed from more than one goroutine. These include the decoding entry points used by the standard library and popular frameworks: Scan, UnmarshalJSON, UnmarshalYAML, UnmarshalText, UnmarshalBinary, and UnmarshalParam.

Accessors that expose the underlying math/big types (for example BigInt and BigRat) return defensive copies rather than the internal state, so the returned *big.Int or *big.Rat may be read or mutated by the caller without affecting other goroutines that share the original Decimal.

The package-level constants Zero, One, Ten, and Hundred are intended to be treated as read-only singletons; do not pass them to APIs that would mutate a Decimal in place.

Index

Examples

Constants

View Source
const (
	PrecisionFixedSize = 4
)

Variables

View Source
var (

	// Zero is the decimal zero value.
	Zero = New(0)
	// One is the decimal one value.
	One = New(1)
	// Ten is the decimal ten value.
	Ten = New(10)
	// Hundred is the decimal one hundred value.
	Hundred = New(100)
)
View Source
var (
	// ErrOverflow indicates a conversion overflowed the target numeric type,
	// such as int64, uint64, or float.
	ErrOverflow = errors.New("decimal: overflow")

	// ErrDivideByZero indicates an attempted division by zero in Quo,
	// QuoRem, or Mod.
	ErrDivideByZero = errors.New("decimal: division by zero")

	// ErrInvalidPrecision indicates a negative precision was supplied where
	// a non-negative value is required.
	ErrInvalidPrecision = errors.New("decimal: invalid precision")

	// ErrInvalidFormat indicates NewFromString failed to parse the input.
	ErrInvalidFormat = errors.New("decimal: invalid format")

	// ErrNegativeRoot indicates an attempt to take an even root of a
	// negative value in Sqrt or ApproxRoot.
	ErrNegativeRoot = errors.New("decimal: negative value for even root")

	// ErrInvalidRoot indicates a root value that is not strictly positive
	// was supplied to ApproxRoot.
	ErrInvalidRoot = errors.New("decimal: invalid root")

	// ErrInvalidLog indicates an attempt to take the logarithm of a
	// non-positive value.
	ErrInvalidLog = errors.New("decimal: log of non-positive value")

	// ErrRoundUnnecessary indicates rounding was required but
	// RoundUnnecessary was specified.
	ErrRoundUnnecessary = errors.New("decimal: rounding is necessary but RoundUnnecessary specified")

	// ErrUnmarshal indicates an unmarshal operation failed to parse input
	// into a Decimal.
	ErrUnmarshal = errors.New("decimal: unmarshal failed")

	// ErrInvalidArgument indicates an invalid argument was supplied to a
	// package-level function, typically during setup (for example a nil
	// validator or a missing required translation message).
	ErrInvalidArgument = errors.New("decimal: invalid argument")
)

Sentinel errors returned by the decimal package.

These errors are wrapped by the package's functions so that callers may use errors.Is to identify a specific failure category without pattern matching on the error message.

Functions

func Between

func Between(v, lower, upper Decimal) bool

Between reports whether v is within the inclusive range [lower, upper].

Example
fmt.Println(Between(New(5), New(1), New(10)))
Output:
true

func DefaultGoPlaygroundValidatorTranslationMessages added in v0.2.0

func DefaultGoPlaygroundValidatorTranslationMessages(locale string) map[string]string

DefaultGoPlaygroundValidatorTranslationMessages returns built-in translation templates for Decimal validation tags by locale (with English fallback).

func MostSignificantBit

func MostSignificantBit(x *big.Int) uint

MostSignificantBit returns the index of the most significant set bit in x. It returns 0 for x == 0 and panics if x < 0.

Example
fmt.Println(MostSignificantBit(big.NewInt(16)))
Output:
4

func RegisterGoPlaygroundValidator added in v0.2.0

func RegisterGoPlaygroundValidator(v *validator.Validate) error

RegisterGoPlaygroundValidator registers Decimal-specific validation tags for go-playground/validator.

Registered tags:

  • decimal_required
  • decimal_eq
  • decimal_ne
  • decimal_gt
  • decimal_gte
  • decimal_lt
  • decimal_lte
  • decimal_between (param: "min~max" — tilde-separated bounds, inclusive; min must be <= max)
  • decimal_positive
  • decimal_negative
  • decimal_nonzero
  • decimal_max_precision (param: non-negative integer, max number of decimal places (scale); see validateDecimalMaxPrecision)

Use built-in omitempty as usual.

Validator tag parameters must be compile-time constants. Passing malformed parameters (non-numeric limits, unparseable decimal values, min > max for decimal_between, negative decimal_max_precision) causes panics at validation time — do not splice untrusted input into struct tags.

Calling this function multiple times on the same *validator.Validate is safe and idempotent: re-registration overwrites the previous handler for each tag.

Example
v := validator.New()
_ = decimal.RegisterGoPlaygroundValidator(v)

type Req struct {
	Price decimal.Decimal `validate:"decimal_required,decimal_positive,decimal_max_precision=2"`
	Rate  decimal.Decimal `validate:"decimal_between=0~1"`
}

good := Req{
	Price: decimal.MustFromString("9.99"),
	Rate:  decimal.MustFromString("0.25"),
}
fmt.Println(v.Struct(good))

bad := Req{
	Price: decimal.MustFromString("9.999"), // too many decimal places
	Rate:  decimal.MustFromString("0.25"),
}
err := v.Struct(bad)
if verr, ok := err.(validator.ValidationErrors); ok {
	fmt.Println(verr[0].Tag())
}
Output:
<nil>
decimal_max_precision

func RegisterGoPlaygroundValidatorTranslations added in v0.2.0

func RegisterGoPlaygroundValidatorTranslations(v *validator.Validate, trans ut.Translator) error

RegisterGoPlaygroundValidatorTranslations registers friendly error messages for Decimal validator tags on the provided translator.

It selects built-in messages by trans.Locale(), with English fallback. Built-in locales: en, zh (Simplified), zh_Hant (Traditional Chinese, also matches zh_TW), ja, ko, fr, es, de, pt, pt_BR, ru, ar, hi.

func RegisterGoPlaygroundValidatorTranslationsWithMessages added in v0.2.0

func RegisterGoPlaygroundValidatorTranslationsWithMessages(v *validator.Validate, trans ut.Translator, messages map[string]string) error

RegisterGoPlaygroundValidatorTranslationsWithMessages registers friendly Decimal validator messages using caller-provided templates.

Any missing tag message falls back to English defaults.

func TranslateGoPlaygroundValidationErrors added in v0.2.0

func TranslateGoPlaygroundValidationErrors(err error, trans ut.Translator) []string

TranslateGoPlaygroundValidationErrors converts validator errors into friendly messages.

Types

type Decimal

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

Decimal represents a decimal number with arbitrary precision.

func Max

func Max(a, b Decimal) Decimal

Max returns the greater of a and b.

Example
fmt.Println(Max(New(1), New(2)))
Output:
2

func Min

func Min(a, b Decimal) Decimal

Min returns the smaller of a and b.

Example
fmt.Println(Min(New(1), New(2)))
Output:
1

func MustFromString

func MustFromString(str string) Decimal

MustFromString returns a Decimal parsed from str and panics if parsing fails.

Example
fmt.Println(MustFromString("12.34"))
Output:
12.34

func New

func New(value int64) Decimal

New returns a Decimal created from value with precision 0.

Example
fmt.Println(New(42))
Output:
42

func NewFromBigInt

func NewFromBigInt(value *big.Int) Decimal

NewFromBigInt returns a Decimal created from value with precision 0.

Example
fmt.Println(NewFromBigInt(big.NewInt(123)))
Output:
123

func NewFromBigIntWithPrec

func NewFromBigIntWithPrec(value *big.Int, precision int) Decimal

NewFromBigIntWithPrec returns a Decimal created from value with the given precision. It panics if precision is negative.

Example
fmt.Println(NewFromBigIntWithPrec(big.NewInt(12345), 2))
Output:
123.45

func NewFromBigRat

func NewFromBigRat(value *big.Rat) (Decimal, error)

NewFromBigRat returns a Decimal converted from value.

It returns an error when value is nil or cannot be represented as a terminating decimal (for example 1/3).

Example
d, err := NewFromBigRat(big.NewRat(7, 4))
fmt.Println(d, err == nil)
Output:
1.75 true

func NewFromBigRatWithPrec

func NewFromBigRatWithPrec(value *big.Rat, prec int, roundingMode RoundingMode) (Decimal, error)

NewFromBigRatWithPrec returns a Decimal converted from value at precision prec.

The result is rounded according to roundingMode. It returns an error when value is nil and panics when prec is negative.

Example
d, err := NewFromBigRatWithPrec(big.NewRat(1, 3), 2, RoundHalfEven)
fmt.Println(d, err == nil)
Output:
0.33 true

func NewFromDecimal added in v0.3.0

func NewFromDecimal(d Decimal) Decimal

NewFromDecimal returns a deep copy of d. It is provided for API symmetry with the other NewFrom* constructors and is equivalent to d.Clone().

Example
src := MustFromString("3.14")
dst := NewFromDecimal(src)
fmt.Println(dst)
Output:
3.14

func NewFromFloat32

func NewFromFloat32(value float32) Decimal

NewFromFloat32 returns a Decimal parsed from value.

Example
fmt.Println(NewFromFloat32(12.34))
Output:
12.34

func NewFromFloat64

func NewFromFloat64(value float64) Decimal

NewFromFloat64 returns a Decimal parsed from value.

Example
fmt.Println(NewFromFloat64(12.34))
Output:
12.34

func NewFromInt

func NewFromInt(value int) Decimal

NewFromInt returns a Decimal created from value with precision 0.

Example
fmt.Println(NewFromInt(42))
Output:
42

func NewFromInt64

func NewFromInt64(value int64, precision int) Decimal

NewFromInt64 returns a Decimal created from value with the given precision. It panics if precision is negative.

Example
fmt.Println(NewFromInt64(12345, 2))
Output:
123.45

func NewFromString

func NewFromString(str string) (d Decimal, err error)

NewFromString returns a Decimal parsed from str.

It accepts plain decimal values and scientific notation, and returns an error for empty or malformed input.

Example
d, err := NewFromString("00123.4500")
if err != nil {
	panic(err)
}

fmt.Println(d.String())
fmt.Println(d.StringWithTrailingZeros())
Output:
123.45
123.4500
Example (Negative)
d, err := NewFromString("-00123.4500")
if err != nil {
	panic(err)
}

fmt.Println(d.String())
fmt.Println(d.StringWithTrailingZeros())
Output:
-123.45
-123.4500
Example (ScientificNotation)
d1, err := NewFromString("1.23456e3")
if err != nil {
	panic(err)
}
d2, err := NewFromString("-4.56E-2")
if err != nil {
	panic(err)
}

fmt.Println(d1.String())
fmt.Println(d2.String())
fmt.Println(d2.StringWithTrailingZeros())
Output:
1234.56
-0.0456
-0.0456

func NewFromUint64

func NewFromUint64(value uint64, precision int) Decimal

NewFromUint64 returns a Decimal created from value with the given precision. It panics if precision is negative.

Example
fmt.Println(NewFromUint64(12345, 2))
Output:
123.45

func NewFromUintWithAppendPrec

func NewFromUintWithAppendPrec(value uint64, prec int) Decimal

NewFromUintWithAppendPrec returns a Decimal created from value with prec trailing zeros appended. It panics if prec is negative.

Example
fmt.Println(NewFromUintWithAppendPrec(12, 3).StringWithTrailingZeros())
Output:
12.000

func NewWithAppendPrec

func NewWithAppendPrec(value int64, prec int) Decimal

NewWithAppendPrec returns a Decimal created from value with prec trailing zeros appended. It panics if prec is negative.

Example
fmt.Println(NewWithAppendPrec(12, 3).StringWithTrailingZeros())
Output:
12.000

func NewWithPrec

func NewWithPrec(value int64, prec int) Decimal

NewWithPrec returns a Decimal created from value with the given precision. It panics if prec is negative.

Example
fmt.Println(NewWithPrec(1234, 2))
Output:
12.34

func (Decimal) Abs

func (d Decimal) Abs() Decimal

Abs returns the absolute value of d.

Example
fmt.Println(New(-1).Abs())
Output:
1

func (Decimal) Add

func (d Decimal) Add(d2 Decimal) Decimal

Add returns d + d2, rescaled to the larger precision of the two values.

Example
sum := MustFromString("1.20").Add(MustFromString("2.34"))
rounded := MustFromString("2.555").Rescale(2, RoundHalfEven)

fmt.Println(sum.String())
fmt.Println(rounded.String())
Output:
3.54
2.56
Example (DifferentPrecision)
r := MustFromString("1.2").Add(MustFromString("0.030"))
fmt.Println(r.String(), r.Precision())
fmt.Println(r.StringWithTrailingZeros())
Output:
1.23 3
1.230

func (Decimal) AddRaw

func (d Decimal) AddRaw(i int64) Decimal

AddRaw returns d + i while preserving d's precision.

Example
fmt.Println(MustFromString("1.23").AddRaw(1))
Output:
1.24

func (Decimal) ApproxRoot

func (d Decimal) ApproxRoot(root int64) (Decimal, error)

ApproxRoot returns an approximate integer-th root of d using iterative refinement.

Note: since v0.3.0 the output precision is max(d.Precision(), 30), which is a breaking change relative to v0.2.x where the result matched the receiver precision exactly. Callers that need the previous behavior should use ApproxRootWithPrec(root, d.Precision()) explicitly.

It returns an error wrapping ErrInvalidRoot when root is not strictly positive, or ErrNegativeRoot when d is negative and root is even. The output precision is max(d.prec, defaultLogExpPrec).

Example
v, err := MustFromString("3125.0000").ApproxRoot(5)
fmt.Println(v, err == nil)
Output:
5 true

func (Decimal) ApproxRootWithPrec added in v0.3.0

func (d Decimal) ApproxRootWithPrec(root int64, prec int) (Decimal, error)

ApproxRootWithPrec returns an approximate integer-th root of d rescaled to prec decimal places using RoundHalfEven.

Note: since v0.3.0 callers that pass prec smaller than 30 still observe a lifted working precision internally, but the final result is rescaled to the requested prec. Pass d.Precision() to reproduce the v0.2.x behavior of matching the receiver precision.

It returns an error wrapping ErrInvalidRoot when root is not strictly positive, or ErrNegativeRoot when d is negative and root is even. It panics if prec is negative.

Example
v, _ := MustFromString("27").ApproxRootWithPrec(3, 6)
fmt.Println(v)
Output:
3

func (Decimal) BigInt

func (d Decimal) BigInt() *big.Int

BigInt returns a copy of the underlying big.Int value.

Example
fmt.Println(MustFromString("12.34").BigInt())
Output:
1234

func (Decimal) BigRat

func (d Decimal) BigRat() *big.Rat

BigRat returns d as an exact rational value.

Example
fmt.Println(MustFromString("12.34").BigRat().RatString())
Output:
617/50

func (Decimal) BitLen

func (d Decimal) BitLen() int

BitLen returns the bit length of d's underlying integer representation.

Example
fmt.Println(New(7).BitLen())
Output:
3

func (Decimal) Ceil

func (d Decimal) Ceil() Decimal

Ceil returns the least integer value greater than or equal to d.

Example
fmt.Println(MustFromString("-1.2").Ceil())
Output:
-1

func (Decimal) CeilWithPrec

func (d Decimal) CeilWithPrec(prec int) Decimal

CeilWithPrec returns d rounded toward positive infinity at the given precision. It panics if prec is negative.

Example
fmt.Println(MustFromString("-1.239").CeilWithPrec(2))
Output:
-1.23

func (Decimal) Clone added in v0.3.0

func (d Decimal) Clone() Decimal

Clone returns a deep copy of d. The returned Decimal shares no mutable state with d, so mutating the underlying big.Int of either value will not affect the other.

Example
original := MustFromString("42.5")
copy := original.Clone()
fmt.Println(copy.Equal(original))
Output:
true

func (Decimal) Cmp

func (d Decimal) Cmp(d2 Decimal) int

Cmp compares d and d2 and returns:

-1 if d < d2
 0 if d == d2
+1 if d > d2
Example
fmt.Println(New(1).Cmp(New(2)))
Output:
-1

func (Decimal) Equal

func (d Decimal) Equal(d2 Decimal) bool

Equal returns true if d and d2 are equal.

Example
fmt.Println(New(1).Equal(New(1)))
Output:
true

func (Decimal) Exp added in v0.3.0

func (d Decimal) Exp() (Decimal, error)

Exp returns an approximate value of e raised to the power of d.

It evaluates the Taylor series e^x = sum_{n>=0} x^n / n! with argument reduction: e^x = (e^(x/2^k))^(2^k). The reduction shrinks |x| below 0.5, which guarantees rapid convergence. The iteration is bounded by maxIterations.

Example
result, _ := MustFromString("0").Exp()
fmt.Println(result)
Output:
1

func (Decimal) ExpWithPrec added in v0.3.0

func (d Decimal) ExpWithPrec(prec int) (Decimal, error)

ExpWithPrec returns e^d rescaled to prec decimal places using RoundHalfEven.

It panics if prec is negative.

Example
result, _ := MustFromString("1").ExpWithPrec(4)
fmt.Println(result)
Output:
2.7183

func (Decimal) Float32

func (d Decimal) Float32() (float32, bool)

Float32 returns the nearest float32 value for d and whether it is exact.

Example
v, exact := MustFromString("0.5").Float32()
fmt.Println(v, exact)
Output:
0.5 true

func (Decimal) Float64

func (d Decimal) Float64() (float64, bool)

Float64 returns the nearest float64 value for d and whether it is exact.

Example
v, exact := MustFromString("0.5").Float64()
fmt.Println(v, exact)
Output:
0.5 true

func (Decimal) Floor

func (d Decimal) Floor() Decimal

Floor returns the greatest integer value less than or equal to d.

Example
fmt.Println(MustFromString("-1.2").Floor())
Output:
-2

func (Decimal) FloorWithPrec

func (d Decimal) FloorWithPrec(prec int) Decimal

FloorWithPrec returns d rounded toward negative infinity at the given precision. It panics if prec is negative.

Example
fmt.Println(MustFromString("-1.239").FloorWithPrec(2))
Output:
-1.24

func (Decimal) Format added in v0.3.0

func (d Decimal) Format(f fmt.State, verb rune)

Format implements fmt.Formatter, providing support for the common numeric verbs along with width, precision, and flag handling.

Supported verbs:

%v, %s  the canonical string form (same as String)
%q      the canonical string form wrapped in quotes
%d      the integer value; only valid for integer Decimals. Non-integer
        values produce the %!d(decimal.Decimal=<string>) error marker so
        callers do not silently truncate fractional digits.
%f      fixed-point notation; precision selects fractional digits
%e, %E  scientific notation (default precision 6)
%g, %G  the shorter of %e or %f for the given precision
%b      binary representation of the unscaled big.Int with a scale tag

Width, precision, '-', '+', ' ', and '0' flags are honored where they make sense for the chosen verb.

Example
d := MustFromString("1234.5678")
fmt.Printf("%s\n", d)
fmt.Printf("%.2f\n", d)
fmt.Printf("%e\n", d)
Output:
1234.5678
1234.57
1.234568e+03

func (Decimal) FormatWithSeparators added in v0.3.0

func (d Decimal) FormatWithSeparators(thousands, decimal rune) string

FormatWithSeparators returns d formatted with the supplied thousands and decimal separators. A thousands value of 0 disables grouping. A decimal value of 0 is treated as a zero rune and falls back to '.' so the output is always a syntactically valid decimal literal. The fractional part keeps its full precision as produced by StringWithTrailingZeros.

Example
d := MustFromString("1234567.89")
fmt.Println(d.FormatWithSeparators(',', '.'))
fmt.Println(d.FormatWithSeparators('.', ','))
fmt.Println(d.FormatWithSeparators(' ', '.'))
Output:
1,234,567.89
1.234.567,89
1 234 567.89

func (Decimal) GT

func (d Decimal) GT(d2 Decimal) bool

GT returns true if d is greater than d2.

Example
fmt.Println(New(2).GT(New(1)))
Output:
true

func (Decimal) GTE

func (d Decimal) GTE(d2 Decimal) bool

GTE returns true if d is greater than or equal to d2.

Example
fmt.Println(New(2).GTE(New(2)))
Output:
true

func (Decimal) HasFraction

func (d Decimal) HasFraction() bool

HasFraction returns true if d has a fractional part.

Example
fmt.Println(MustFromString("1.25").HasFraction())
Output:
true

func (Decimal) Int64

func (d Decimal) Int64() (int64, bool)

Int64 returns d as an int64 if it is an exact integer in range.

Example
v, ok := MustFromString("42.0").Int64()
fmt.Println(v, ok)
Output:
42 true

func (Decimal) IntPart

func (d Decimal) IntPart() *big.Int

IntPart returns the integer part of d.

Example
fmt.Println(MustFromString("12.34").IntPart())
Output:
12

func (Decimal) IsInteger

func (d Decimal) IsInteger() bool

IsInteger returns true if d has no fractional part.

Example
fmt.Println(MustFromString("1.000").IsInteger())
Output:
true

func (Decimal) IsNegative

func (d Decimal) IsNegative() bool

IsNegative returns true if d is negative.

Example
fmt.Println(New(-1).IsNegative())
Output:
true

func (Decimal) IsNil

func (d Decimal) IsNil() bool

IsNil returns true if d has no underlying value.

Example
var d Decimal
fmt.Println(d.IsNil())
Output:
true

func (Decimal) IsNotZero

func (d Decimal) IsNotZero() bool

IsNotZero returns true if d is not zero.

Example
fmt.Println(New(1).IsNotZero())
Output:
true

func (Decimal) IsPositive

func (d Decimal) IsPositive() bool

IsPositive returns true if d is positive.

Example
fmt.Println(New(1).IsPositive())
Output:
true

func (Decimal) IsZero

func (d Decimal) IsZero() bool

IsZero returns true if d is zero or nil.

Example
fmt.Println(New(0).IsZero())
Output:
true

func (Decimal) LT

func (d Decimal) LT(d2 Decimal) bool

LT returns true if d is less than d2.

Example
fmt.Println(New(1).LT(New(2)))
Output:
true

func (Decimal) LTE

func (d Decimal) LTE(d2 Decimal) bool

LTE returns true if d is less than or equal to d2.

Example
fmt.Println(New(1).LTE(New(1)))
Output:
true

func (Decimal) Ln added in v0.3.0

func (d Decimal) Ln() (Decimal, error)

Ln returns an approximate natural logarithm of d.

It returns an error wrapping ErrInvalidLog when d is not strictly positive. Internally Ln is computed as Log2(d) * ln(2) using a pre-computed high-precision constant for ln(2).

Example
x := MustFromString("2.718281828459045235360287")
result, _ := x.Ln()
fmt.Println(result.Rescale(6, RoundHalfEven))
Output:
1

func (Decimal) LnWithPrec added in v0.3.0

func (d Decimal) LnWithPrec(prec int) (Decimal, error)

LnWithPrec returns an approximate natural logarithm of d rescaled to prec decimal places using RoundHalfEven.

It returns an error wrapping ErrInvalidLog when d is not strictly positive. It panics if prec is negative.

func (Decimal) Log2

func (d Decimal) Log2() Decimal

Log2 returns an approximate log base 2 of d via iterative refinement. The iteration is bounded by maxIterations. It panics if d is not greater than 0.

Example
fmt.Println(New(8).Log2())
Output:
3

func (Decimal) Log10 added in v0.3.0

func (d Decimal) Log10() (Decimal, error)

Log10 returns an approximate base-10 logarithm of d.

It returns an error wrapping ErrInvalidLog when d is not strictly positive. Internally Log10 is computed as Log2(d) / Log2(10) at the receiver's precision (bumped to defaultLogExpPrec when the receiver has fewer fractional digits). The result is rescaled to the receiver's precision so that callers receive output in a familiar scale.

Example
x := MustFromString("100")
result, _ := x.Log10()
fmt.Println(result.Rescale(0, RoundHalfEven))
Output:
2

func (Decimal) Log10WithPrec added in v0.3.0

func (d Decimal) Log10WithPrec(prec int) (Decimal, error)

Log10WithPrec returns an approximate base-10 logarithm of d rescaled to prec decimal places using RoundHalfEven.

It returns an error wrapping ErrInvalidLog when d is not strictly positive. It panics if prec is negative.

Example
result, _ := MustFromString("1000").Log10WithPrec(2)
fmt.Println(result)
Output:
3

func (Decimal) Marshal

func (d Decimal) Marshal() ([]byte, error)

Marshal implements gogo-protobuf custom type marshaling via MarshalBinary.

Example
bz, err := MustFromString("1.23").Marshal()
fmt.Println(len(bz) > 0 && err == nil)
Output:
true

func (Decimal) MarshalBinary

func (d Decimal) MarshalBinary() (data []byte, err error)

MarshalBinary implements encoding.BinaryMarshaler. The binary layout is 4 bytes of big-endian precision followed by big.Int Gob bytes. It strips trailing zeros before encoding and returns nil for an uninitialized value.

Example
bz, err := MustFromString("1.23").MarshalBinary()
fmt.Println(len(bz) > 0 && err == nil)
Output:
true

func (Decimal) MarshalJSON

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

MarshalJSON implements json.Marshaler. It encodes a decimal as a JSON string and encodes an uninitialized value as null.

Example
bz, _ := MustFromString("1.23").MarshalJSON()
fmt.Println(string(bz))
Output:
"1.23"

func (Decimal) MarshalText

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

MarshalText implements encoding.TextMarshaler by returning the decimal string form.

Example
bz, _ := MustFromString("1.23").MarshalText()
fmt.Println(string(bz))
Output:
1.23

func (Decimal) MarshalTo

func (d Decimal) MarshalTo(data []byte) (n int, err error)

MarshalTo implements gogo-protobuf custom type marshaling into data.

Example
d := MustFromString("1.23")
buf := make([]byte, d.Size())
n, err := d.MarshalTo(buf)
fmt.Println(n > 0 && err == nil)
Output:
true

func (Decimal) MarshalXML added in v0.3.0

func (d Decimal) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler. It encodes the decimal as character data using the canonical string form. An uninitialized Decimal is encoded as an empty element.

Example
package main

import (
	"bytes"
	"encoding/xml"
	"fmt"

	"github.com/exc-works/decimal"
)

func main() {
	type Item struct {
		XMLName xml.Name        `xml:"item"`
		Amount  decimal.Decimal `xml:"amount"`
	}

	var buf bytes.Buffer
	enc := xml.NewEncoder(&buf)
	_ = enc.Encode(Item{Amount: decimal.MustFromString("42.5")})
	fmt.Println(buf.String())
}
Output:
<item><amount>42.5</amount></item>

func (Decimal) MarshalXMLAttr added in v0.3.0

func (d Decimal) MarshalXMLAttr(name xml.Name) (xml.Attr, error)

MarshalXMLAttr implements xml.MarshalerAttr. An uninitialized Decimal yields an attribute with an empty value.

func (Decimal) MarshalYAML

func (d Decimal) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler by returning the decimal string form.

Example
v, _ := MustFromString("1.23").MarshalYAML()
fmt.Println(v)
Output:
1.23

func (Decimal) Max

func (d Decimal) Max(d2 Decimal) Decimal

Max returns the larger of d and d2.

Example
fmt.Println(New(1).Max(New(2)))
Output:
2

func (Decimal) Min

func (d Decimal) Min(d2 Decimal) Decimal

Min returns the smaller of d and d2.

Example
fmt.Println(New(1).Min(New(2)))
Output:
1

func (Decimal) Mod

func (d Decimal) Mod(d2 Decimal) Decimal

Mod returns the same remainder component as QuoRem (truncated division). It panics if d2 is zero.

Example
fmt.Println(MustFromString("-7").Mod(New(3)))
Output:
-1

func (Decimal) Mul

func (d Decimal) Mul(d2 Decimal, roundingMode RoundingMode) Decimal

Mul returns d * d2 rounded according to roundingMode.

Example
fmt.Println(MustFromString("1.25").Mul(MustFromString("2.00"), RoundHalfEven))
Output:
2.5
Example (DifferentPrecision)
r := MustFromString("1.234").Mul(MustFromString("2.5"), RoundHalfEven)
fmt.Println(r.String(), r.Precision())
Output:
3.085 3

func (Decimal) Mul2 deprecated

func (d Decimal) Mul2(d2 Decimal) Decimal

Mul2 returns d * d2 without rounding, using the sum of input precisions.

Deprecated: use MulExact instead.

func (Decimal) MulDown

func (d Decimal) MulDown(d2 Decimal) Decimal

MulDown returns d * d2 rounded down.

Example
fmt.Println(MustFromString("1.25").MulDown(MustFromString("2.00")))
Output:
2.5

func (Decimal) MulExact

func (d Decimal) MulExact(d2 Decimal) Decimal

MulExact returns d * d2 without rounding, using the sum of input precisions.

Example
fmt.Println(MustFromString("1.20").MulExact(MustFromString("2.30")).StringWithTrailingZeros())
Output:
2.7600

func (Decimal) MustNonNegative

func (d Decimal) MustNonNegative() Decimal

MustNonNegative returns d and panics if d is negative.

Example
fmt.Println(New(1).MustNonNegative())
Output:
1

func (Decimal) Neg

func (d Decimal) Neg() Decimal

Neg returns the negated decimal.

Example
fmt.Println(New(1).Neg())
Output:
-1

func (Decimal) NotEqual

func (d Decimal) NotEqual(d2 Decimal) bool

NotEqual returns true if d and d2 are not equal.

Example
fmt.Println(New(1).NotEqual(New(2)))
Output:
true

func (Decimal) Power

func (d Decimal) Power(power int64) Decimal

Power returns d raised to the given integer power.

Example
fmt.Println(MustFromString("1.5").Power(3))
Output:
3.4

func (Decimal) Precision

func (d Decimal) Precision() int

Precision returns the number of decimal places in d.

Example
fmt.Println(MustFromString("1.23").Precision())
Output:
2

func (Decimal) Quo

func (d Decimal) Quo(d2 Decimal, roundingMode RoundingMode) Decimal

Quo returns d / d2 rounded according to roundingMode. It panics if d2 is zero or roundingMode is invalid.

Example
fmt.Println(New(7).Quo(New(2), RoundDown))
Output:
3
Example (DifferentPrecision)
r := MustFromString("12.3").Quo(MustFromString("0.20"), RoundHalfEven)
fmt.Println(r.String(), r.Precision())
fmt.Println(r.StringWithTrailingZeros())
Output:
61.5 2
61.50

func (Decimal) QuoDown

func (d Decimal) QuoDown(d2 Decimal) Decimal

QuoDown returns d / d2 rounded down.

Example
fmt.Println(New(7).QuoDown(New(2)))
Output:
3

func (Decimal) QuoRem

func (d Decimal) QuoRem(d2 Decimal) (Decimal, Decimal)

QuoRem returns the quotient truncated toward zero and the corresponding remainder. It panics if d2 is zero.

Example
q, r := MustFromString("-7").QuoRem(New(3))
fmt.Println(q, r)
Output:
-2 -1

func (Decimal) QuoWithPrec

func (d Decimal) QuoWithPrec(d2 Decimal, prec int, roundingMode RoundingMode) Decimal

QuoWithPrec returns d / d2 rounded to prec decimal places using roundingMode. It panics if prec is negative, d2 is zero, or roundingMode is invalid.

Example
fmt.Println(New(1).QuoWithPrec(New(3), 6, RoundHalfEven))
Output:
0.333333

func (Decimal) Remainder

func (d Decimal) Remainder() (intPart *big.Int, fractionPart *big.Int)

Remainder returns the integer part and fractional part of d.

Example
i, f := MustFromString("12.34").Remainder()
fmt.Println(i, f)
Output:
12 34

func (Decimal) Rescale

func (d Decimal) Rescale(prec int, roundingMode RoundingMode) Decimal

Rescale returns d rescaled to prec decimal places using roundingMode. It panics if prec is negative or roundingMode is invalid.

Example
d := MustFromString("7.5000").Rescale(2, RoundDown)
bz, err := d.MarshalJSON()
if err != nil {
	panic(err)
}

fmt.Println(d.StringWithTrailingZeros())
fmt.Println(string(bz))
Output:
7.50
"7.5"

func (Decimal) RescaleDown

func (d Decimal) RescaleDown(prec int) Decimal

RescaleDown returns d rescaled to prec decimal places using RoundDown. It panics if prec is negative.

Example
fmt.Println(MustFromString("1.29").RescaleDown(1))
Output:
1.2

func (Decimal) Round

func (d Decimal) Round() Decimal

Round returns d rounded to the nearest integer using RoundHalfEven.

Example
fmt.Println(MustFromString("2.5").Round())
fmt.Println(MustFromString("3.5").Round())
Output:
2
4

func (Decimal) RoundWithPrec

func (d Decimal) RoundWithPrec(prec int) Decimal

RoundWithPrec returns d rounded to the given precision using RoundHalfEven. It panics if prec is negative.

Example
fmt.Println(MustFromString("1.245").RoundWithPrec(2))
Output:
1.24

func (Decimal) SafeAdd

func (d Decimal) SafeAdd(d2 Decimal) Decimal

SafeAdd returns d + d2 and panics if the result is negative.

Example
fmt.Println(New(2).SafeAdd(New(3)))
Output:
5

func (Decimal) SafeSub

func (d Decimal) SafeSub(d2 Decimal) Decimal

SafeSub returns d - d2 and panics if the result is negative.

Example
fmt.Println(New(5).SafeSub(New(2)))
Output:
3

func (*Decimal) Scan

func (d *Decimal) Scan(value any) error

Scan implements sql.Scanner. It accepts nil, float32, float64, int64, string, and []byte inputs, and updates d in place. Nil input resets d to its uninitialized state.

Example
var d Decimal
_ = d.Scan("1.23")
fmt.Println(d)
Output:
1.23

func (Decimal) Shift

func (d Decimal) Shift(places int) Decimal

Shift returns d multiplied by 10^places exactly.

Positive places shift the decimal point to the right; negative places shift it to the left.

Example
fmt.Println(MustFromString("12.34").Shift(2))
fmt.Println(MustFromString("12.34").Shift(-3))
Output:
1234
0.01234

func (Decimal) Sign

func (d Decimal) Sign() int

Sign returns:

-1 if d < 0
 0 if d == 0
+1 if d > 0
Example
fmt.Println(New(-1).Sign())
Output:
-1

func (Decimal) SignificantFigures

func (d Decimal) SignificantFigures(figures int, roundingMode RoundingMode) Decimal

SignificantFigures returns d rounded to figures significant figures. It may round within the fractional part or to tens/hundreds on the integer part. It panics if figures is not greater than 0.

Example
fmt.Println(MustFromString("123.456").SignificantFigures(4, RoundHalfEven))
fmt.Println(MustFromString("123.456").SignificantFigures(3, RoundHalfEven))
fmt.Println(MustFromString("123.456").SignificantFigures(2, RoundHalfEven))
Output:
123.5
123
120

func (Decimal) Size

func (d Decimal) Size() int

Size implements gogo-protobuf custom type sizing based on Marshal output.

Example
fmt.Println(MustFromString("1.23").Size() > 0)
Output:
true

func (Decimal) Sqrt

func (d Decimal) Sqrt() (Decimal, error)

Sqrt returns an approximate square root of d.

Note: since v0.3.0 the output precision is max(d.Precision(), 30), which is a breaking change relative to v0.2.x where the result matched the receiver precision exactly. Callers that need the previous behavior should use SqrtWithPrec(d.Precision()) explicitly.

It returns an error wrapping ErrNegativeRoot when d is negative. The output precision is max(d.prec, defaultLogExpPrec) so that integer receivers still produce meaningful results.

Example
v, err := MustFromString("16.0").Sqrt()
fmt.Println(v, err == nil)
Output:
4 true

func (Decimal) SqrtWithPrec added in v0.3.0

func (d Decimal) SqrtWithPrec(prec int) (Decimal, error)

SqrtWithPrec returns an approximate square root of d rescaled to prec decimal places using RoundHalfEven.

Note: since v0.3.0 callers that pass prec smaller than 30 still observe a lifted working precision internally, but the final result is rescaled to the requested prec. Pass d.Precision() to reproduce the v0.2.x behavior of matching the receiver precision.

It returns an error wrapping ErrNegativeRoot when d is negative. It panics if prec is negative.

Example
v, _ := MustFromString("2").SqrtWithPrec(10)
fmt.Println(v)
Output:
1.4142135624

func (Decimal) String

func (d Decimal) String() string

String removes trailing zeros from the decimal representation.

Example
fmt.Println(MustFromString("1.2300").String())
Output:
1.23

func (Decimal) StringWithTrailingZeros

func (d Decimal) StringWithTrailingZeros() string

StringWithTrailingZeros returns the string with trailing zeros in the decimal representation.

Example
fmt.Println(MustFromString("1.2300").StringWithTrailingZeros())
Output:
1.2300

func (Decimal) StripTrailingZeros

func (d Decimal) StripTrailingZeros() Decimal

StripTrailingZeros returns a Decimal which is numerically equal to this one but with any trailing zeros removed from the representation.

Example
fmt.Println(MustFromString("1.2300").StripTrailingZeros())
Output:
1.23

func (Decimal) Sub

func (d Decimal) Sub(d2 Decimal) Decimal

Sub returns d - d2, rescaled to the larger precision of the two values.

Example
fmt.Println(MustFromString("5.5").Sub(MustFromString("2.2")))
Output:
3.3
Example (DifferentPrecision)
r := MustFromString("5.00").Sub(MustFromString("0.125"))
fmt.Println(r.String(), r.Precision())
Output:
4.875 3

func (Decimal) SubRaw

func (d Decimal) SubRaw(i int64) Decimal

SubRaw returns d - i while preserving d's precision.

Example
fmt.Println(MustFromString("5.5").SubRaw(1))
Output:
5.4

func (Decimal) Truncate

func (d Decimal) Truncate() Decimal

Truncate returns d rounded toward zero to an integer value.

Example
fmt.Println(MustFromString("-1.9").Truncate())
Output:
-1

func (Decimal) TruncateWithPrec

func (d Decimal) TruncateWithPrec(prec int) Decimal

TruncateWithPrec returns d rounded toward zero at the given precision. It panics if prec is negative.

Example
fmt.Println(MustFromString("-1.239").TruncateWithPrec(2))
Output:
-1.23

func (Decimal) Uint64

func (d Decimal) Uint64() (uint64, bool)

Uint64 returns d as a uint64 if it is a non-negative exact integer in range.

Example
v, ok := MustFromString("42.0").Uint64()
fmt.Println(v, ok)
Output:
42 true

func (*Decimal) Unmarshal

func (d *Decimal) Unmarshal(data []byte) error

Unmarshal implements gogo-protobuf custom type unmarshaling via UnmarshalBinary.

Example
src := MustFromString("1.23")
bz, _ := src.Marshal()
var dst Decimal
_ = dst.Unmarshal(bz)
fmt.Println(dst)
Output:
1.23

func (*Decimal) UnmarshalBinary

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

UnmarshalBinary implements encoding.BinaryUnmarshaler. It expects the MarshalBinary layout, resets d to zero for empty input, and returns an error when data is shorter than the fixed precision prefix.

Example
src := MustFromString("1.23")
bz, _ := src.MarshalBinary()
var dst Decimal
_ = dst.UnmarshalBinary(bz)
fmt.Println(dst)
Output:
1.23

func (*Decimal) UnmarshalJSON

func (d *Decimal) UnmarshalJSON(bz []byte) error

UnmarshalJSON implements json.Unmarshaler. It accepts JSON strings and JSON numbers, treats null as a no-op, and updates d in place.

Example
var d Decimal
_ = d.UnmarshalJSON([]byte(`"1.23"`))
fmt.Println(d)
Output:
1.23

func (*Decimal) UnmarshalParam added in v0.2.0

func (d *Decimal) UnmarshalParam(param string) error

UnmarshalParam implements gin's BindUnmarshaler by parsing decimal text.

func (*Decimal) UnmarshalText

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

UnmarshalText implements encoding.TextUnmarshaler by parsing decimal text.

Example
var d Decimal
_ = d.UnmarshalText([]byte("1.23"))
fmt.Println(d)
Output:
1.23

func (*Decimal) UnmarshalXML added in v0.3.0

func (d *Decimal) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler. It parses character data into a Decimal via NewFromString. Empty content leaves d as the uninitialized zero Decimal.

func (*Decimal) UnmarshalXMLAttr added in v0.3.0

func (d *Decimal) UnmarshalXMLAttr(attr xml.Attr) error

UnmarshalXMLAttr implements xml.UnmarshalerAttr. An empty attribute value leaves d as the uninitialized zero Decimal.

func (*Decimal) UnmarshalYAML

func (d *Decimal) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml unmarshaling by decoding scalar values into Decimal.

Example
var d Decimal
_ = d.UnmarshalYAML(func(target any) error {
	p := target.(*any)
	*p = "1.23"
	return nil
})
fmt.Println(d)
Output:
1.23

func (Decimal) Value

func (d Decimal) Value() (driver.Value, error)

Value implements driver.Valuer by returning the canonical decimal string form.

Example
v, _ := MustFromString("1.23").Value()
fmt.Println(v)
Output:
1.23

type NullDecimal added in v0.3.0

type NullDecimal struct {
	Decimal Decimal
	Valid   bool // Valid is true if Decimal is not NULL
}

NullDecimal is a nullable Decimal, mirroring the pattern used by database/sql's NullString. The zero value represents SQL NULL.

Example
package main

import (
	"fmt"

	"github.com/exc-works/decimal"
)

func main() {
	n := decimal.NewNullDecimal(decimal.MustFromString("9.99"))
	fmt.Println(n.Valid, n.Decimal)

	var empty decimal.NullDecimal
	fmt.Println(empty.Valid, empty.String())
}
Output:
true 9.99
false null

func NewNullDecimal added in v0.3.0

func NewNullDecimal(d Decimal) NullDecimal

NewNullDecimal returns a NullDecimal wrapping d with Valid set to true.

func (NullDecimal) MarshalJSON added in v0.3.0

func (n NullDecimal) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. An invalid NullDecimal is encoded as JSON null.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/exc-works/decimal"
)

func main() {
	valid := decimal.NewNullDecimal(decimal.MustFromString("1.5"))
	validBytes, _ := json.Marshal(valid)

	var invalid decimal.NullDecimal
	invalidBytes, _ := json.Marshal(invalid)

	fmt.Println(string(validBytes))
	fmt.Println(string(invalidBytes))
}
Output:
"1.5"
null

func (NullDecimal) MarshalText added in v0.3.0

func (n NullDecimal) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. An invalid NullDecimal is encoded as an empty byte slice.

func (NullDecimal) MarshalXML added in v0.3.0

func (n NullDecimal) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler. An invalid NullDecimal is encoded as an empty element; otherwise the call is delegated to Decimal.MarshalXML.

func (NullDecimal) MarshalXMLAttr added in v0.3.0

func (n NullDecimal) MarshalXMLAttr(name xml.Name) (xml.Attr, error)

MarshalXMLAttr implements xml.MarshalerAttr. An invalid NullDecimal returns an empty xml.Attr which encoding/xml omits. Otherwise the call is delegated to Decimal.MarshalXMLAttr.

func (NullDecimal) MarshalYAML added in v0.3.0

func (n NullDecimal) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler. An invalid NullDecimal is encoded as the YAML nil value.

func (*NullDecimal) Scan added in v0.3.0

func (n *NullDecimal) Scan(value any) error

Scan implements sql.Scanner. A nil value resets n to an invalid zero state. Any other value is delegated to Decimal.Scan and marks n valid on success.

func (NullDecimal) String added in v0.3.0

func (n NullDecimal) String() string

String returns "null" when n is not valid, otherwise Decimal.String.

func (*NullDecimal) UnmarshalJSON added in v0.3.0

func (n *NullDecimal) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. JSON null sets Valid to false; any other value is parsed via Decimal.UnmarshalJSON.

Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/exc-works/decimal"
)

func main() {
	var valid decimal.NullDecimal
	_ = json.Unmarshal([]byte(`"2.5"`), &valid)
	fmt.Println(valid.Valid, valid.Decimal)

	var null decimal.NullDecimal
	_ = json.Unmarshal([]byte(`null`), &null)
	fmt.Println(null.Valid)
}
Output:
true 2.5
false

func (*NullDecimal) UnmarshalParam added in v0.3.0

func (n *NullDecimal) UnmarshalParam(param string) error

UnmarshalParam implements gin's BindUnmarshaler. An empty string marks the value invalid; any other value is delegated to Decimal.UnmarshalParam.

func (*NullDecimal) UnmarshalText added in v0.3.0

func (n *NullDecimal) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler. Empty text sets Valid to false; any other value is parsed via Decimal.UnmarshalText.

func (*NullDecimal) UnmarshalXML added in v0.3.0

func (n *NullDecimal) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler. Empty character content sets Valid to false; any other value is delegated to Decimal.UnmarshalXML and marks n valid on success.

func (*NullDecimal) UnmarshalXMLAttr added in v0.3.0

func (n *NullDecimal) UnmarshalXMLAttr(attr xml.Attr) error

UnmarshalXMLAttr implements xml.UnmarshalerAttr. An empty attribute value sets Valid to false; any other value is delegated to Decimal.UnmarshalXMLAttr and marks n valid on success.

func (*NullDecimal) UnmarshalYAML added in v0.3.0

func (n *NullDecimal) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml unmarshaling. A nil scalar sets Valid to false; other scalars are delegated to Decimal.UnmarshalYAML.

func (NullDecimal) Value added in v0.3.0

func (n NullDecimal) Value() (driver.Value, error)

Value implements driver.Valuer by returning nil when n is not valid, otherwise the canonical string form from Decimal.Value.

type RoundingMode

type RoundingMode int
const (
	// RoundDown rounds towards zero.
	RoundDown RoundingMode = iota
	// RoundUp rounds away from zero.
	RoundUp
	// RoundCeiling rounds towards positive infinity.
	RoundCeiling
	// RoundHalfUp rounds to nearest; ties round up.
	RoundHalfUp
	// RoundHalfDown rounds to nearest; ties round down.
	RoundHalfDown
	// RoundHalfEven rounds to nearest; ties to even.
	RoundHalfEven
	// RoundUnnecessary asserts no rounding is required.
	RoundUnnecessary
)

Jump to

Keyboard shortcuts

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