finanza/decimal
Fixed-point decimal arithmetic with explicit rounding.
A Decimal is represented internally as a signed
integer coefficient and an exponent:
value = coefficient × 10^exponent
Decimal is pub opaque; construct values through from_int,
from_string, or new, and inspect them through
coefficient and exponent.
Precision boundary
On the JavaScript target, Gleam’s Int is a 64-bit IEEE 754 number,
so coefficients are limited to ±(2^53 − 1) = 9_007_199_254_740_991.
Operations that would produce a larger coefficient return
PrecisionExceeded. On the Erlang target,
integers are arbitrary precision; the same bound is enforced anyway
so behaviour is consistent across targets.
Types
Errors returned by arithmetic operations.
pub type ArithmeticError {
DivisionByZero
PrecisionExceeded
}
Constructors
Fixed-point decimal value. Construct via from_int,
from_string, or new.
pub opaque type Decimal
Errors returned by from_string.
pub type ParseError {
EmptyInput
InvalidCharacter(char: String, position: Int)
MultipleDecimalPoints
MultipleSigns
NoDigits
ParsedValueTooLarge
}
Constructors
-
EmptyInputThe input was the empty string or contained only whitespace.
-
InvalidCharacter(char: String, position: Int)The input contained a character that is not a digit, sign, or decimal point.
-
MultipleDecimalPointsThe input contained more than one decimal point.
-
MultipleSignsThe input contained more than one sign character.
-
NoDigitsThe input contained no digits (e.g.
"+",".","-."). -
ParsedValueTooLargeThe parsed coefficient would exceed
±9_007_199_254_740_991(the JavaScript-safe integer ceiling). Such a value cannot be represented faithfully on the JavaScript target; rather than silently corrupt it (and emit unparseable strings fromto_string), parsing fails fast.
Values
pub fn add(
a a: Decimal,
b b: Decimal,
) -> Result(Decimal, ArithmeticError)
Add two decimals.
pub fn compare(a a: Decimal, b b: Decimal) -> order.Order
Total ordering. Two values with the same numeric value compare as equal even when their exponents differ.
pub fn divide(
a a: Decimal,
b b: Decimal,
digits digits: Int,
mode mode: rounding.Mode,
) -> Result(Decimal, ArithmeticError)
Divide a by b, returning a result rounded to digits decimal
places using mode.
Returns DivisionByZero when b is zero, or
PrecisionExceeded when the intermediate
representation would exceed ±9_007_199_254_740_991.
pub fn equal(a a: Decimal, b b: Decimal) -> Bool
Equality test by numeric value, not by representation.
equal(new(coefficient: 100, exponent: -2), one()) is True.
pub fn format(
d d: Decimal,
thousands thousands: String,
decimal_separator decimal_separator: String,
) -> String
Render a Decimal with custom thousands and decimal separators.
format(d, thousands: ",", decimal_separator: ".") // "1,234.56"
format(d, thousands: ".", decimal_separator: ",") // "1.234,56" (German)
format(d, thousands: "", decimal_separator: ".") // "1234.56"
Equivalent to to_string when thousands is empty
and decimal_separator is ".".
pub fn from_string(
input input: String,
) -> Result(Decimal, ParseError)
Parse a decimal from a string. Accepts an optional leading + or
-, decimal digits, and at most one . separator. Scientific
notation is not supported.
from_string("3.14") // Ok(Decimal with coefficient=314, exponent=-2)
from_string("-0.5") // Ok(Decimal with coefficient=-5, exponent=-1)
from_string("") // Error(EmptyInput)
from_string("1.2.3") // Error(MultipleDecimalPoints)
pub fn multiply(
a a: Decimal,
b b: Decimal,
) -> Result(Decimal, ArithmeticError)
Multiply two decimals.
pub fn negate(d d: Decimal) -> Decimal
Negate the value. Always safe (the coefficient sign flips but magnitude does not change).
pub fn new(
coefficient coefficient: Int,
exponent exponent: Int,
) -> Decimal
Build a Decimal directly from a coefficient and exponent.
new(coefficient: 1234, exponent: -2) represents 12.34.
pub fn rescale(
d d: Decimal,
target_exponent target_exponent: Int,
mode mode: rounding.Mode,
) -> Result(Decimal, ArithmeticError)
Force the decimal to a specific exponent. When the new exponent is
finer (smaller), the coefficient grows by zero-padding (may overflow).
When the new exponent is coarser (larger), digits are dropped using
mode.
pub fn round(
d d: Decimal,
digits digits: Int,
mode mode: rounding.Mode,
) -> Decimal
Round to digits decimal places. When the input is already at
equal or coarser precision, the original Decimal is returned
unchanged (no zero-padding); call rescale to force a
target exponent.
pub fn subtract(
a a: Decimal,
b b: Decimal,
) -> Result(Decimal, ArithmeticError)
Subtract b from a.
pub fn to_string(d d: Decimal) -> String
Render a Decimal as a plain string. Preserves the encoded
exponent (new(coefficient: 100, exponent: -2) renders as "1.00",
not "1").