Standard library · Numbers
num/decimal
Imported as import "num/decimal" as decimal, its names are then decimal.…. Every signature below is the one the checker infers.
Decimal numbers with a fixed number of places: money, and anything else where 0.1 + 0.2 has to be 0.3.
A Decimal is an integer count of units and a scale, the number of places: Decimal(1250, 2) is 12.50. Adding and comparing align the scales; multiplying keeps every place and rounds only when asked; dividing takes the places to keep and how to round. The count is an Int, so eighteen digits in all is the limit, and a result past it is the wrong number rather than an error — the same as Int itself.
price = decimal.parse("19.99")? total = decimal.mul(price, decimal.from_int(3)) total # => 59.97 vat = decimal.round_to(decimal.mul(total, decimal.parse("0.20")?), 2, decimal.HalfEven) decimal.add(total, vat) # => 71.96
Types
Decimal
Decimal(units: Int, scale: Int)
Rounding
HalfUpHalfEvenDownUp
Implementations
impl Show(Decimal)impl Ord(Decimal)
Functions
fn from_int(n: Int) -> Decimal
decimal.from_int(12) # => 12
fn zero() -> Decimal
decimal.zero() # => 0
fn is_zero(d: Decimal) -> Bool
decimal.is_zero(decimal.parse("0.00")?) # => true
fn neg(d: Decimal) -> Decimal
decimal.neg(decimal.parse("1.50")?) # => -1.50
fn abs_of(d: Decimal) -> Decimal
decimal.abs_of(decimal.parse("-1.50")?) # => 1.50
fn sign(d: Decimal) -> Int
decimal.sign(decimal.parse("-0.01")?) # => -1
fn round_to(d: Decimal, places: Int, how: Rounding) -> Decimal
The same number at places places — more, exactly; fewer, rounded.
decimal.round_to(decimal.parse("2.345")?, 2, decimal.HalfUp) # => 2.35 decimal.round_to(decimal.parse("2.345")?, 2, decimal.HalfEven) # => 2.34 decimal.round_to(decimal.parse("2.349")?, 2, decimal.Down) # => 2.34 decimal.round_to(decimal.parse("2.341")?, 2, decimal.Up) # => 2.35 decimal.round_to(decimal.parse("2.5")?, 3, decimal.HalfUp) # => 2.500
fn add(a: Decimal, b: Decimal) -> Decimal
decimal.add(decimal.parse("0.1")?, decimal.parse("0.2")?) # => 0.3
fn sub(a: Decimal, b: Decimal) -> Decimal
decimal.sub(decimal.parse("1.00")?, decimal.parse("0.75")?) # => 0.25
fn mul(a: Decimal, b: Decimal) -> Decimal
Exact: the places add up. Round afterwards where a money amount wants its two.
decimal.mul(decimal.parse("1.5")?, decimal.parse("1.5")?) # => 2.25
fn div(a: Decimal, b: Decimal, places: Int, how: Rounding) -> Result(Decimal, Str)
a / b to places places, rounded as asked; Err on a zero divisor.
decimal.div(decimal.from_int(1), decimal.from_int(3), 4, decimal.HalfUp) # => Ok(0.3333) decimal.div(decimal.from_int(1), decimal.zero(), 2, decimal.HalfUp) # => Err(division by zero)
fn cmp(a: Decimal, b: Decimal) -> Int
decimal.cmp(decimal.parse("1.10")?, decimal.parse("1.1")?) # => 0
fn eq(a: Decimal, b: Decimal) -> Bool
decimal.eq(decimal.parse("1.10")?, decimal.parse("1.1")?) # => true
fn as_float(d: Decimal) -> Float
decimal.as_float(decimal.parse("12.50")?) # => 12.5
fn text(d: Decimal) -> Str
-12.50 for Decimal(-1250, 2); a scale of zero prints no point.
decimal.text(decimal.Decimal(-1250, 2)) # => -12.50 decimal.text(decimal.Decimal(7, 0)) # => 7
fn parse(s: Str) -> Result(Decimal, Str)
12, 12.5, -0.75, +3.00: digits with at most one point.
decimal.parse("+3.00") # => Ok(3.00) decimal.parse("1.2.3") # => Err(`1.2.3` has two points)
Tests
test_text_and_parsetest_arithmetictest_rounding