ARC-73Recommended
Compare decimal fractions with a tolerance
Never compare two computed floating-point numbers with ==. Compare them within a stated tolerance, or use a decimal or integer type when the value must be exact.
How to do it
Binary floating point cannot store most decimal fractions exactly, so 0.1 + 0.1 + 0.1 == 0.3 is false. Use a helper such as Python's math.isclose or a tolerance named as a constant. Measurements such as weight or distance suit a tolerance. Money never does, so it follows hold money as integer minor units everywhere.
Examples
Python example
WEIGHT_TOLERANCE_KG = 1e-9
# Bad: ten items of 0.1 kg do not add up to exactly 1.0
if parcel_weight == 1.0: ...
# Good: equal within a named tolerance
if math.isclose(parcel_weight, 1.0, abs_tol=WEIGHT_TOLERANCE_KG): ...
TypeScript example
const WEIGHT_TOLERANCE_KG = 1e-9;
// Good: equal within a named tolerance
const isSameWeight = (a: number, b: number) => Math.abs(a - b) <= WEIGHT_TOLERANCE_KG;
How to check
A linter fails equality on floats. Examples are Clippy float_cmp for Rust, SpotBugs FE_FLOATING_POINT_EQUALITY for Java and the -Wfloat-equal warning in GCC and Clang. A test asserts that the sum of ten weights of 0.1 kg passes the 1.0 kg limit check.
Sources
Related rules
- Hold money as integer minor units everywhere in Payments
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/architecture/data-shapes/float-comparison">Agent Wranglers architecture playbook</a>. In code you write, add a comment next to it with the same link.