Precise decimal arithmetic for financial calculations — No floating-point errors. Part of the Simple Eiffel ecosystem.
✅ Production Ready — v1.0.0
- Arbitrary-precision decimal arithmetic
- Financial operations (currency, percentage, split)
- Full Design by Contract coverage
Binary floating-point (REAL, DOUBLE) cannot represent many decimal fractions exactly:
-- DOUBLE fails silently!
io.put_double (0.1 + 0.2) -- Outputs: 0.30000000000000004 WRONG!This causes real-world problems:
- Financial calculations that don't balance
- Prices that display incorrectly
- Tax calculations that are off by a penny
- Cumulative errors in accounting systems
SIMPLE_DECIMAL uses arbitrary-precision decimal arithmetic:
local
a, b, total: SIMPLE_DECIMAL
do
create a.make ("0.1")
create b.make ("0.2")
total := a + b
print (total.out) -- Outputs: 0.3 CORRECT!
endclass
INVOICE_CALCULATOR
feature -- Calculation
calculate_total (subtotal_str: STRING; tax_rate_str: STRING): STRING
-- Calculate total with tax, returning formatted currency
local
subtotal, tax_rate, tax, total: SIMPLE_DECIMAL
do
create subtotal.make (subtotal_str)
create tax_rate.make (tax_rate_str)
-- Calculate tax: subtotal * (rate / 100)
tax := (subtotal * tax_rate.from_percentage).round_cents
total := subtotal + tax
Result := total.to_currency_string
end
endUsage:
calculator.calculate_total ("47.99", "8.25") -- Returns: "$51.95"-- From string (most precise)
create price.make ("19.99")
create rate.make ("0.0825")
-- From integer
create count.make_from_integer (42)
-- From dollars and cents
create amount.make_currency (19, 99) -- $19.99
-- Special values
create zero.make_zero
create one.make_oneAll operations are immutable (return new SIMPLE_DECIMAL):
result := a + b -- Addition
result := a - b -- Subtraction
result := a * b -- Multiplication
result := a / b -- Division
result := a // b -- Integer division
result := a \ b -- Modulo (remainder)
result := a.negate -- Negation
result := a.absolute -- Absolute valueif price < budget then ...
if a <= b then ...
if total > limit then ...
if a >= b then ...
if a.is_equal (b) then ...-- Round to cents (2 decimal places)
total := price.round_cents
-- Round to N decimal places
pi := value.round (4) -- 3.1416
-- Rounding modes
up := value.round_up (2) -- Away from zero
down := value.round_down (2) -- Toward zero
ceil := value.round_ceiling (2) -- Toward +infinity
floor := value.round_floor (2) -- Toward -infinity
trunc := value.truncate -- Remove fractional part-- Percentage calculations
tax := subtotal.add_percent (tax_rate) -- Add 8.25% tax
sale := price.subtract_percent (discount) -- Subtract 20% discount
-- Convert between decimal and percentage
rate := decimal.as_percentage -- 0.0825 -> 8.25
decimal := rate.from_percentage -- 8.25 -> 0.0825
-- Split bill
parts := bill.split (3) -- Split $100 into 3 equal parts
-- Returns: [$33.34, $33.33, $33.33] (sum equals original)print (amount.out) -- "1234.56"
print (amount.to_string) -- "1234.56"
print (amount.to_currency_string) -- "$1,234.56"
print (amount.dollars.out) -- "1234"
print (amount.cents.out) -- "56"Add to your environment (one-time setup for all simple_* libraries):
export SIMPLE_EIFFEL=D:\prodAdd to your project's .ecf file:
<library name="simple_decimal" location="$SIMPLE_EIFFEL/simple_decimal/simple_decimal.ecf"/>- EiffelStudio 25.02+
- Gobo Math Library (included with EiffelStudio)
cd /path/to/simple_decimal
ec.exe -batch -config simple_decimal.ecf -target simple_decimal_tests -c_compile
# Run tests
./EIFGENs/simple_decimal_tests/W_code/simple_decimal.exeMIT License - See LICENSE file.
Part of the Simple Eiffel ecosystem.