How do I work with money and currency in EK9?

← Getting Started · Ref: Q35

EK9 has a built-in Money type with literal syntax, automatic rounding, and per-currency precision. No financial library needed.

MONEY LITERALS

Format: amount#CURRENCY using ISO 4217 three-letter currency codes:

  10#GBP            British pounds (auto-padded to 10.00#GBP)
  30.20#USD         US dollars
  6798.9288#CLF     Chilean Unidad de Fomento (4 decimal places)
  1500#JPY          Japanese yen (0 decimal places)

The compiler knows every ISO 4217 currency and its correct decimal precision. GBP and USD use 2 decimals, JPY uses 0, CLF uses 4. Amounts are automatically padded or rounded to the correct precision for the currency. Money() creates an unset money value.

AUTOMATIC ROUNDING

EK9 uses HALF_UP rounding — the rounding everyone learns in school. When the digit being dropped is 5 or above, round away from zero:

  99.51#GBP / 2 = 49.755 rounds to 49.76#GBP

Rounding is automatic and uses each currency's correct precision. You never need to specify a rounding mode or scale.

ARITHMETIC OPERATORS

Addition and subtraction work between money values of the SAME currency:

  money + money      Addition (10#GBP + 89.51#GBP = 99.51#GBP)
  money - money      Subtraction (500#GBP - 100#GBP = 400#GBP)

Multiplication and division scale by a Float or Integer:

  money * float      49.76#GBP * -8.754 = -435.60#GBP
  money / integer    99.51#GBP / 2 = 49.76#GBP (HALF_UP)

Dividing money by money gives the ratio as a Float:

  935.60#GBP / 155.93#GBP = 6.0001 (a Float, not Money)

COMPOUND ASSIGNMENT

  working += 4.07#GBP     Add to existing
  working -= 0.56#GBP     Subtract from existing
  working *= 0.666        Multiply by factor
  working /= 4            Divide by number

UNARY OPERATORS

  -amount          Negation
  abs amount       Absolute value
  sqrt amount      Square root (rounded to currency precision)
  amount ^ 6       Power (exponentiation)

COMPARISON

Money supports ==, <>, <, >, <=, >=, <=> for same-currency comparison.

See Q149 for currency safety (mixed currency, division by zero, and why Money is built-in). See Q150 for currency conversion and locale formatting. Use 'ek9 -h Money' to see the full API.

See Q36 for dimension. See Q149 for money safety.

Example

defines module qa.money

  defines program
    MoneyDemo()
      stdout <- Stdout()

      // === MONEY LITERALS ===

      // Format: amount#CURRENCY using ISO 4217 codes
      tenPounds <- 10#GBP
      thirtyDollars <- 30.20#USD
      chilean <- 6798.9288#CLF
      stdout.println(`GBP: ${tenPounds}`)
      stdout.println(`USD: ${thirtyDollars}`)
      stdout.println(`CLF: ${chilean}`)

      // Auto-padding: 10#GBP equals 10.00#GBP
      require tenPounds == 10.00#GBP

      // Unset money
      unsetMoney <- Money()
      require ~unsetMoney?

      // === ARITHMETIC WITH AUTO-ROUNDING ===

      // Addition (same currency only)
      total <- tenPounds + 89.51#GBP
      require total == 99.51#GBP
      stdout.println(`Total: ${total}`)

      // Division rounds using HALF_UP: 99.51 / 2 = 49.755 rounds to 49.76
      halved <- total / 2
      require halved == 49.76#GBP
      stdout.println(`Halved (HALF_UP): ${halved}`)

      // Multiply by Float
      negativeAmount <- halved * -8.754
      require negativeAmount == -435.60#GBP
      stdout.println(`Negative: ${negativeAmount}`)

      // Subtraction
      recovery <- 500#GBP - negativeAmount
      require recovery == 935.60#GBP

      // Complex expression
      calculated <- (recovery * 3) / 18
      require calculated == 155.93#GBP
      stdout.println(`Calculated: ${calculated}`)

      // Money / Money gives Float (the ratio)
      ratio <- recovery / calculated
      stdout.println(`Ratio: ${ratio}`)

      // === COMPOUND ASSIGNMENT ===

      working <- 155.93#GBP
      working += 4.07#GBP
      require working == 160.00#GBP

      working *= 0.666
      require working == 106.56#GBP

      working -= 0.56#GBP
      require working == 106.00#GBP

      working /= 4
      require working == 26.50#GBP

      // === UNARY OPERATORS ===

      // Negation
      working := -working
      require working == -26.50#GBP

      // Absolute value
      working := abs working
      require working == 26.50#GBP

      // Square root
      working := sqrt working
      require working == 5.15#GBP

      // Power
      working := working ^ 6
      require working == 18657.07#GBP
      stdout.println(`After power: ${working}`)

      // === COMPARISON ===

      require tenPounds < total
      require total > tenPounds
      require tenPounds <> total
      require tenPounds <= 10.00#GBP
      require tenPounds >= 10.00#GBP

Common mistakes

E50060 — EK9 Money uses operators for arithmetic, not method calls. Use + for addition, - for subtraction, not .add() or .subtract(). Triggers E50060 — method not resolved. See ek9 -h Money for the full API.

Incorrect:

tenPounds.add(89.51#GBP)

Correct:

tenPounds + 89.51#GBP
Other ways to ask this
  • Does EK9 have a built-in money type?
  • How does EK9 handle currency arithmetic and rounding?
  • What arithmetic operations can I do with Money in EK9?
  • How does rounding work for Money in EK9?

Coming from another language?

Java: BigDecimal with explicit RoundingMode at every operation, verbose new BigDecimal("10.50").multiply(rate).setScale(2, RoundingMode.HALF_UP), Currency class separate from amount, no literal syntax, mixed currency not detected. Python: decimal.Decimal requires context for rounding, no currency awareness, money libraries (py-moneyed) needed. JavaScript: IEEE 754 floating-point causes 0.1+0.2!=0.3 bugs, Dinero.js or similar needed. Ruby: no built-in, money gem needed. Go: no built-in, shopspring/decimal or similar. Rust: no built-in, rust_decimal crate. C#: decimal type has precision but no currency, no literal syntax for currency. EK9: built-in amount#CURRENCY literals, automatic HALF_UP rounding, per-currency precision, mixed currency safety, stream collection, currency conversion, no imports needed.

Keywords: rounding, financial, half_up, money, currency, precision, decimal, first, gbp, start, usd, exchange, intro, convert, beginner, arithmetic, iso4217