FLOAT and DOUBLE are binary approximations - 0.1 has no exact representation. Sums of currency drift by fractions of a cent, and the drift compounds.
CREATE TABLE bad (amount DOUBLE PRECISION);
CREATE TABLE good (amount NUMERIC(12, 2));
INSERT INTO bad SELECT 0.1 FROM generate_series(1, 10);
INSERT INTO good SELECT 0.1 FROM generate_series(1, 10);
SELECT SUM(amount) FROM bad;
SELECT SUM(amount) FROM good;
SELECT 0.1::float8 + 0.2::float8 = 0.3::float8 AS float_eq;
bad : 0.9999999999999999
good : 1.00
float_eq: false
-- NUMERIC(12,2) is exact and slower. For money that trade is not a trade.
-- Storing minor units as a BIGINT (cents) is the other correct answer.
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-08-25