std/decimal
Operations on the arbitrary-precision, exact base-10 Decimal type:
conversions to/from Int/Float/String, explicit-rounding division and
quantization (every rounding op names a RoundingMode), sign/scale/abs
helpers, and the value-based (scale-insensitive) arithmetic/Equatable/Comparable/
Hashable impls. + - * are exact; only Decimal.divide and
Decimal.round round.
Import with import std/decimal.
Exports
Section titled “Exports”Types
type Decimal
Section titled “type Decimal”type Decimal
Arbitrary-precision exact base-10 number. The third blessed numeric type
alongside Int and Float: + - * are always exact, / is exact-or-trap,
and there is no implicit conversion to/from Int or Float. Literals carry
a d suffix (1.50d); scale is significant for display (1.50d prints
“1.50”) but equality is scale-insensitive (1.50d == 1.5d).
Decimal.from_int
Section titled “Decimal.from_int”fn from_int(n: Int): Decimal
type function on Decimal
Exact conversion of an Int to a Decimal (scale 0). Total.
Interactive Tests
assert Decimal.from_int(42) == 42d
assert Decimal.from_int(-7) == -7d
Decimal.from_string
Section titled “Decimal.from_string”fn from_string(s: String): Maybe<Decimal>
type function on Decimal
Parses a plain base-10 numeric string into a Decimal. Accepts an optional
sign, _ digit separators, and a single fractional part; the number of
digits after the . becomes the scale ("1.50" → scale 2). Exponent
notation is NOT accepted. Returns None for empty or malformed input.
Interactive Tests
assert Decimal.from_string("1.50") == Some(1.50d)
assert Decimal.from_string("1_000") == Some(1000d)
assert Decimal.from_string("oops") == None
Decimal.to_int
Section titled “Decimal.to_int”fn to_int(d: Decimal): Maybe<Int>
type function on Decimal
Converts a Decimal to an Int by truncating toward zero. Returns None when
the truncated value falls outside Int64’s range (~±9.22e18). Use
Decimal.round first if a different rounding rule is needed.
Interactive Tests
assert Decimal.to_int(3.7d) == Some(3)
assert Decimal.to_int(-3.7d) == Some(-3)
Decimal.to_float
Section titled “Decimal.to_float”fn to_float(d: Decimal): Float
type function on Decimal
Converts a Decimal to a Float. Total and lossy-by-nature (Float is binary64, so most base-10 fractions are not exactly representable). Magnitudes beyond Float’s range become ±Infinity. Explicit by design — there is no implicit Decimal→Float coercion.
Interactive Tests
assert Decimal.to_float(1.50d) == 1.5
Decimal.from_float
Section titled “Decimal.from_float”fn from_float(f: Float, scale: Int, mode: RoundingMode): Maybe<Decimal>
type function on Decimal
Converts a Float to a Decimal at exactly the requested scale, rounding the
Float’s exact binary value with mode. Requires an explicit scale and mode
so it can never silently hand back 0.1000…0055. Returns None for NaN and
±Infinity. A runtime error results only when mode is Unnecessary and
rounding would lose information.
Interactive Tests
assert Decimal.from_float(0.1, 2, RoundingMode.HalfEven) == Some(0.10d)
assert Decimal.from_float(3.14159, 2, RoundingMode.Floor) == Some(3.14d)
Decimal.divide
Section titled “Decimal.divide”fn divide(a: Decimal, b: Decimal, scale: Int, mode: RoundingMode): Decimal
type function on Decimal
Divides a / b to exactly scale fractional digits, rounding the quotient
with mode. This is the explicit-rounding division path — unlike the /
operator (exact-or-trap), divide always returns a value at the named scale.
Runtime error on a zero b, or when mode is Unnecessary and the exact
quotient does not fit at scale.
Interactive Tests
assert Decimal.divide(10d, 3d, 2, RoundingMode.HalfEven) == 3.33d
assert Decimal.divide(10.00d, 4d, 2, RoundingMode.Down) == 2.50d
Decimal.round
Section titled “Decimal.round”fn round(d: Decimal, scale: Int, mode: RoundingMode): Decimal
type function on Decimal
Quantizes d to exactly scale fractional digits using mode. Increasing
the scale pads trailing zeros (always exact); decreasing it rounds. A
negative scale rounds to tens/hundreds/… A runtime error results only when
mode is Unnecessary and rounding would lose information.
Interactive Tests
assert Decimal.round(3.14159d, 2, RoundingMode.HalfEven) == 3.14d
assert Decimal.round(2.5d, 0, RoundingMode.HalfEven) == 2d
assert Decimal.round(1d, 2, RoundingMode.Up) == 1.00d
Decimal.normalize
Section titled “Decimal.normalize”fn normalize(d: Decimal): Decimal
type function on Decimal
Strips trailing fractional zeros, returning the value at its minimal scale.
Integer magnitude is never reduced (100d stays 100d, scale 0). Zero
normalizes to scale 0. Equality/hashing already treat scale-equal values as
equal; normalize is for when you want the minimal-scale
representation for display.
Interactive Tests
assert Decimal.normalize(1.50d) == 1.5d
assert Decimal.normalize(100.00d) == 100d
Decimal.scale
Section titled “Decimal.scale”fn scale(d: Decimal): Int
type function on Decimal
Returns the scale (number of fractional digits) of d. Scale is
display-significant — 1.50d has scale 2, 1.5d has scale 1 — even though
the two are ==-equal.
Interactive Tests
assert Decimal.scale(1.50d) == 2
assert Decimal.scale(5d) == 0
Decimal.abs
Section titled “Decimal.abs”fn abs(d: Decimal): Decimal
type function on Decimal
Returns |d| (scale preserved).
Interactive Tests
assert Decimal.abs(-1.50d) == 1.50d
Decimal.negate
Section titled “Decimal.negate”fn negate(d: Decimal): Decimal
type function on Decimal
Returns -d (scale preserved). Negating zero stays zero.
Interactive Tests
assert Decimal.negate(1.50d) == -1.50d
Decimal.sign
Section titled “Decimal.sign”fn sign(d: Decimal): Int
type function on Decimal
Returns the sign of d as -1, 0, or +1 (by mathematical value).
Interactive Tests
assert Decimal.sign(-1.50d) == -1
assert Decimal.sign(0.00d) == 0
assert Decimal.sign(1.50d) == 1
Decimal.zero?
Section titled “Decimal.zero?”fn zero?(d: Decimal): Bool
type function on Decimal
True if d is exactly zero (at any scale: 0d, 0.00d are both zero).
Interactive Tests
assert Decimal.zero?(0.00d)
refute Decimal.zero?(1.50d)
Decimal.min
Section titled “Decimal.min”fn min(a: Decimal, b: Decimal): Decimal
type function on Decimal
Returns the lesser of a and b (by value; ties return a).
Interactive Tests
assert Decimal.min(1.50d, 2d) == 1.50d
Decimal.max
Section titled “Decimal.max”fn max(a: Decimal, b: Decimal): Decimal
type function on Decimal
Returns the greater of a and b (by value; ties return a).
Interactive Tests
assert Decimal.max(1.50d, 2d) == 2d
Decimal.to_string
Section titled “Decimal.to_string”impl Display
fn to_string(d: Decimal): String
impl Display.to_string
Returns the canonical scale-preserving string form of d, matching the
runtime stringifier used by IO.print and string interpolation. Trailing
zeros are kept (1.50d → "1.50").
Interactive Tests
assert Decimal.to_string(1.50d) == "1.50"
assert Decimal.to_string(100d) == "100"
Decimal.add
Section titled “Decimal.add”impl Add
fn add(lhs: Decimal, rhs: Decimal): Decimal
impl Add.add
Decimal.subtract
Section titled “Decimal.subtract”impl Subtract
fn subtract(lhs: Decimal, rhs: Decimal): Decimal
impl Subtract.subtract
Decimal.multiply
Section titled “Decimal.multiply”impl Multiply
fn multiply(lhs: Decimal, rhs: Decimal): Decimal
impl Multiply.multiply
Decimal.inspect
Section titled “Decimal.inspect”impl Debug
fn inspect(d: Decimal): String
impl Debug.inspect
Decimal.equal?
Section titled “Decimal.equal?”impl Equatable
fn equal?(a: Decimal, b: Decimal): Bool
impl Equatable.equal?
Decimal.hash
Section titled “Decimal.hash”impl Hashable
fn hash(d: Decimal): Int
impl Hashable.hash
Decimal.compare
Section titled “Decimal.compare”impl Comparable
fn compare(a: Decimal, b: Decimal): Ordering
impl Comparable.compare
Decimal.step_by
Section titled “Decimal.step_by”impl Steppable
fn step_by(value: Decimal, by: Decimal): Maybe<Decimal>
impl Steppable.step_by
Returns value + by. Decimal stepping is exact because Decimal is
arbitrary-precision base-10.
Interactive Tests
assert Decimal.step_by(1.0d, 0.1d) == Some(1.1d)
enum RoundingMode
Section titled “enum RoundingMode”enum RoundingMode { Up Down Ceiling Floor HalfUp HalfDown HalfEven Unnecessary }
Rounding policy for decimal division and quantization. There is no default: every rounding operation names its mode explicitly.
Up— away from zeroDown— toward zero (truncate)Ceiling— toward +∞Floor— toward −∞HalfUp— nearest; ties away from zeroHalfDown— nearest; ties toward zeroHalfEven— nearest; ties to even (banker’s rounding)Unnecessary— assert exactness; runtime error if rounding is needed
RoundingMode.to_string
Section titled “RoundingMode.to_string”impl Display
fn to_string(value: RoundingMode): String
impl Display.to_string
RoundingMode.inspect
Section titled “RoundingMode.inspect”impl Debug
fn inspect(value: RoundingMode): String
impl Debug.inspect