Floating Point: Why 0.1 + 0.2 Is Not 0.3
Type 0.1 + 0.2 into almost any language and you get 0.30000000000000004. Here is why IEEE 754 binary floating point does that — and how to handle it correctly.
Open a Python REPL, a Node console, or a Ruby prompt and type 0.1 + 0.2. You will not get 0.3. You will get 0.30000000000000004. This is not a bug in any one language — it is how nearly all hardware represents fractional numbers, and understanding it will save you from a class of subtle errors.
Numbers Are Stored in Binary, and Binary Has Limits
Most languages represent decimals using IEEE 754, the standard for binary floating-point arithmetic. A typical double (64-bit float) packs a number into three parts: a sign bit, an exponent, and a mantissa (also called the significand). Think of it as scientific notation in base 2: the value is roughly sign × mantissa × 2^exponent. With 64 bits, the mantissa gets 52 bits, giving you about 15 to 17 significant decimal digits of precision.
The catch is the base 2 part. Just as you cannot write 1/3 exactly in decimal — it is 0.3333… forever — you cannot write certain decimal fractions exactly in binary. A fraction has a finite binary representation only if its denominator is a power of two. So 0.5 (1/2) and 0.25 (1/4) are exact. But 0.1 is 1/10, and 10 is not a power of two, so in binary 0.1 becomes a repeating fraction:
0.1 (decimal) = 0.0001100110011001100... (binary, repeating forever)Since the mantissa is finite, the machine stores the nearest representable value to 0.1, not 0.1 itself. The same happens to 0.2. Neither is the number you typed — each is off by a tiny amount.
Where the Stray Digits Come From
When you compute 0.1 + 0.2, you are not adding the true values. You are adding the two rounded approximations, then rounding the result again to fit back into a double. Those small errors happen to push the sum just above the stored value of 0.3.
>>> 0.1 + 0.20.30000000000000004>>> (0.1 + 0.2) == 0.3False>>> 0.1 + 0.2 - 0.35.551115123125783e-17The leftover 5.5e-17 is the accumulated rounding error. With a single operation it is invisibly small, but errors can accumulate: a loop that adds 0.1 ten thousand times will drift measurably away from 1000. The more operations you chain, the more rounding compounds.
When Floats Are the Wrong Tool
Floating point is the right choice for measurements, physics, graphics, and machine learning — anywhere small relative error is acceptable and speed matters. It is the wrong choice when exactness is required, and money is the classic example. Charging a customer $0.30000000000000004 or watching a running total drift by a penny is unacceptable.
You have two solid alternatives:
- Integers in the smallest unit. Store money as a whole number of cents (or satoshis, or tenths of a cent) and only format to a decimal point for display.
30cents is exact;0.30dollars is not. - A decimal or fixed-point type. Many languages provide arbitrary-precision decimal types — Python’s
decimal.Decimal, Java’sBigDecimal, C#‘sdecimal, SQL’sNUMERIC/DECIMAL. These store numbers in base 10, so 0.1 + 0.2 is exactly 0.3, at the cost of speed.
The rule of thumb: if a human will count the result and care about the last digit, do not use a raw float.
FAQ
Is this a Python bug? It does not happen in my calculator app.+
Does using float instead of double fix it?+
Are integers and decimal types slower?+
Related reading
2026-06-04
ACID vs BASE: What Database Guarantees Actually Promise
ACID and BASE describe two ends of a tradeoff between strict correctness and scalable availability. Learn what each guarantee means, when each fits, and why most modern databases sit somewhere in between.
2026-06-04
Big-Endian vs Little-Endian
Byte order explained: how big-endian and little-endian lay out multi-byte numbers in memory, why network protocols pick one, and when the difference actually bites you.
2026-06-04
Big-O Notation in Plain English
Big-O describes how an algorithm's runtime or memory grows as input grows. Learn the common classes — O(1), O(log n), O(n), O(n log n), O(n^2), O(2^n) — with plain examples.
2026-06-04
CORS in Plain English: Why the Browser Blocks Your Fetch
A clear walkthrough of CORS and the same-origin policy — what an origin is, why your fetch fails, how servers opt in, and the big misconception about who CORS actually protects.
2026-06-04
Environment Variables and PATH, Explained
What environment variables actually are, why they hold config and secrets, and how PATH decides which binary runs when you type a command.
Get the best tools, weekly
One email every Friday. No spam, unsubscribe anytime.