Skip to content
Aldridge Dagos Get in touch

N°004 · 2026.04.01 · 5 MIN

How to Handle Money in Code: Integer Cents Over Floating Point

By Aldridge Dagos, operations software engineer


A tall stack of coins lit by warm light, more coins blurred behind.
Use exact arithmetic for money, with explicit currency, scale, and rounding rules.

Open the calculator built into almost any programming language and ask it the simplest question in arithmetic. What is 0.1 plus 0.2? You expect 0.3. What you get is 0.30000000000000004.

That tiny tail is a problem anywhere exact decimal behavior matters. My first rule for money is to avoid binary floating point for authoritative amounts. Integer minor units are one strong design. An exact fixed-point decimal or database numeric type is another. The correct choice depends on currencies, fractional pricing, rates, range, and rounding policy.

The short version: Do not use binary floating point for authoritative money amounts. Store a currency code with either integer minor units or an exact fixed-point decimal. Integer minor units make addition and subtraction simple and exact when the system works at one known scale. Exact decimal types are useful for currencies, tax rates, exchange rates, unit prices, or calculations that need more fractional precision. Define scale and rounding for each operation, allocate remainders deliberately, and enforce range and currency rules in the database.

That is not a quirk of one language. It is true in almost all of them. Computers store decimals in binary, and one tenth has no clean binary form, the same way one third has no clean decimal form. You write 0.1, the machine keeps the closest binary fraction it can, and the tiny error rides along in every sum after it.

For most software this never matters. Off by a fraction of a trillionth, nobody notices. Payroll is the opposite case. A paycheck that is off by a hundredth of a cent is a paycheck that is wrong, and a wrong number on a payslip becomes a phone call, then a spreadsheet argument, then a person who stops trusting the system that pays them. So I treat money as a thing the machine is not allowed to approximate.

Why payroll software should use integer cents, not floating point

The principle is one line. Authoritative money values should use an exact representation, not binary floating point.

A paycheck of forty seven dollars and thirty cents is not 47.30 anywhere in the system. It is 4730. An integer. Integers add, subtract, and multiply with no drift, because there is no fraction for the machine to fumble. The whole class of rounding ghosts is gone, because there is nothing after the decimal point to lose. There is no decimal point.

Representation Best use Important limit
Binary floating point Measurements and approximate numeric work Many decimal fractions are not exact
Integer minor units Posted amounts at a known currency scale Currencies and calculations do not all use two decimals
Exact fixed-point or numeric Rates, fractional unit prices, multi-scale calculations Scale, rounding, range, and performance still need design

For posted payroll amounts in a two-decimal currency, integer minor units are easy to audit. Forty-seven dollars and thirty cents becomes 4,730 minor units. The amount should travel with its currency code so 4,730 is never interpreted without knowing the unit.

Integer cents are not the only exact option. PostgreSQL documents numeric as an exact type and recommends it for monetary amounts and other quantities where exactness is required. A system may calculate with exact decimal values at a higher scale, then round once when it posts a payable amount in the currency’s minor unit.

Keep decimals at the edges of the system

In an integer-minor-unit design, the decimal appears at input and display boundaries. Type 47.30 and the system parses it into 4,730 minor units. Display code formats 4,730 using the currency’s scale. Calculations that create fractions, such as tax, allocation, or foreign exchange, need an exact intermediate representation and an explicit posting rule.

This is the part people skip, and it is the part that holds the whole thing up. A decimal that lives only at the boundary is a display format. A decimal that lives in the core is a leak. I keep the boundary thin and the core clean, so every calculation runs on values that cannot wobble.

Decide the rounding rule once

There is one place this gets sharp, and it is rounding. Take a monthly salary and break it into an hourly rate. Fifty thousand a month, twenty two working days, eight hours a day. Divide it out and you get 284.0909, and the nines never stop. You cannot pay someone a fraction of a cent, so the number has to round, and the only real question is which way.

The rounding rule must follow the business, accounting, contractual, and legal requirement for the operation. Half away from zero is one option. Half even, truncation, and jurisdiction-specific tax rules are others. Document where rounding happens, test boundary cases, and record any allocated remainder so a set of line items reconciles to its total.

I lock this with a test built on the most famous case in computing. Add a tenth and a fifth, the 0.1 and 0.2 that breaks calculators, and the system has to land on exactly thirty cents. Not close. Thirty. If that test ever goes red, the build stops before a wrong number can reach a person.

Make the database refuse a bad number

A rule that lives only in code is a rule that holds until the code has a bad afternoon. So I push it down a layer and make the database itself refuse to hold a wrong number. The place that stores a paycheck carries a rule that the value can never go negative. If a stack of deductions would push someone below zero, the math is not allowed to write a negative paycheck. It clamps to zero, the remainder is recorded as money still owed, and that balance carries into the next run. Nothing gets silently swallowed.

The code enforces this. The database enforces it too. Two locks on the same door. The second lock is the one that proves itself on the day the first one fails, and a paycheck is exactly the kind of number you want guarded twice. It is the same instinct behind a double-entry ledger that refuses to save an unbalanced entry: let the data layer turn the bad number away at the door.

People ask why payroll has to be this strict. It is not strictness for its own sake. It is the gap between approximately right and right, and on a payslip approximately right is the same as wrong. Nobody is impressed that a total was off by a thousandth of a cent. They see a number that is wrong, and once a person catches the system being wrong about their own money, they check every number from then on. The entire value of the system is that they never have to.

The durable rule is small: no binary floating point for authoritative money. Choose integer minor units or an exact decimal model, carry the currency and scale, round deliberately, and make the database reject values outside the design.

Binary floating point cannot represent every decimal fraction exactly. Integer minor units and exact decimal types give money systems a sounder base.

Frequently asked questions

Why is 0.1 + 0.2 not equal to 0.3 in most programming languages?

Because computers store decimals in binary, and one tenth has no exact binary representation, the same way one third has no exact decimal one. The machine keeps the closest value it can, and that tiny rounding error accumulates, so 0.1 + 0.2 lands on 0.30000000000000004.

How should you store money in code?

Use integer minor units or an exact fixed-point decimal, plus a currency code. Integer minor units work well for posted amounts at a known scale. Exact decimal types work well when intermediate calculations need additional fractional precision.

What is integer-cents and why use it for currency?

Integer cents represent a two-decimal currency as a count of its minor units. They remove binary floating-point approximation from posted amounts. They are not a complete design for currencies with other scales, fractional prices, tax rates, or exchange-rate calculations.

How do you handle rounding when splitting an amount?

Choose one rounding rule, state it explicitly, and apply it identically everywhere. A common choice is rounding half away from zero. The rule must be fixed and consistent so the same input always produces the same result, including during an audit.

Should money validation live in the database too?

Yes. A rule enforced only in application code fails the moment the code has a bug. Enforcing it in the database as well, for example refusing to store a negative paycheck, gives you a second lock that holds when the first one slips.