How do I get exact decimals (BigDecimal) in EK9?
← Advanced Type System · Ref: Q1367
Float is 64-bit binary floating point, so it cannot represent values like 0.1 exactly (0.1 + 0.2 is not quite 0.3). When you need EXACT decimals, use BigDecimal - arbitrary-precision decimal arithmetic. (For currency specifically, use Money.)
EXACT ARITHMETIC
sum <- BigDecimal("0.1") + BigDecimal("0.2") // exactly 0.3
+, -, * and ^ are exact. Create from a String (exact), an Integer, or a Float.
EQUALITY IS BY VALUE, NOT SCALE
Unlike java.math.BigDecimal.equals, EK9 compares by value: 1.0 equals 1.00. ==, <=> and #? all use value comparison, so equal values also hash the same.
DIVISION AND SQRT
A non-terminating quotient like 1/3 needs a bound, so division and sqrt keep 34 significant digits (MathContext DECIMAL128). Division by zero is UNSET.
ROUNDING
rounded <- BigDecimal("3.14159").round(2) // 3.14 (HALF_UP)
DISPLAY
$ gives the plain-string form (no scientific notation).
Like BigInteger, BigDecimal has no #^ promote operator. See Q1366 for BigInteger and Q23 for the Money type. Use 'ek9 -h BigDecimal' for the full API.
Example
defines module qa.bigdecimal.usage defines program BigDecimalUsage() stdout <- Stdout() //Exact: 0.1 + 0.2 is exactly 0.3 (Float cannot do this). sum <- BigDecimal("0.1") + BigDecimal("0.2") stdout.println(`sum: ${sum}`) //Equality is by value, not scale: 1.0 equals 1.00. a <- BigDecimal("1.0") b <- BigDecimal("1.00") equal <- a == b stdout.println(`1.0 == 1.00: ${equal}`) //Round to a number of decimal places. rounded <- BigDecimal("3.14159").round(2) stdout.println(`rounded: ${rounded}`)
Other ways to ask this
- Why is 0.1 + 0.2 not 0.3 with Float?
- How do I do high-precision decimal arithmetic?
- What do I use for exact decimals that are not money?
Coming from another language?
Java: java.math.BigDecimal - but equals is scale-sensitive (1.0 != 1.00); EK9 compares by value. Python: decimal.Decimal. Go: shopspring/decimal or math/big Rat. Rust: rust_decimal. EK9: BigDecimal is built in; exact (0.1+0.2==0.3); value equality (1.0==1.00); DECIMAL128 division; round(places); no #^ promote. Use Money for currency.
Keywords: value, bigdecimal, scale, precision, rounding, arithmetic, exact, money, equality, 0.1, 0.3, float, decimal