---
title: "0.1 + 0.2 = 0.30000000000000004: not a bug, a binary fraction"
url: https://erroneo.us/daily/floating-point-0-1-plus-0-2/
description: "0.1 + 0.2 gives 0.30000000000000004 because binary floats can't store 0.1 exactly. Compare with a tolerance; use decimals or integer cents for money."
type: daily-entry
section: "Developers"
date_published: 2026-10-27
author: erroneo.us Editors
date_modified: 2026-10-27
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---

# 0.1 + 0.2 = 0.30000000000000004: not a bug, a binary fraction

> Every language that uses standard hardware floating point gets this "wrong" the same way. Here's why, and the three habits that keep it out of your bug tracker.

*Error of the Day for October 27, 2026 · Developers · by erroneo.us Editors*

- **Wrong:** if (0.1 + 0.2 === 0.3) { /* never runs */ }
- **Right:** if (Math.abs((0.1 + 0.2) - 0.3) < Number.EPSILON) { /* runs */ }  // or math.isclose() in Python
- **Memory trick:** Binary can't write 0.1 any more than decimal can write 1/3. Never test floats with ==.

## What people get wrong

Open a browser console or a Python prompt and try it:

```
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
```

The usual reaction is that the language is broken. It isn't. The [Python documentation](https://docs.python.org/3/tutorial/floatingpoint.html) says it plainly: this is in the very nature of binary floating point, "not a bug in Python, and it is not a bug in your code either," and you will see the same thing in every language that uses your hardware's floating-point arithmetic. [MDN shows the identical result](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON) for JavaScript.

## Why it happens

Computers store most non-integer numbers in binary floating-point formats defined by [IEEE 754](https://standards.ieee.org/ieee/754/6210/). JavaScript's `Number` and Python's `float` are both 64-bit doubles.

The catch: binary can only represent fractions exactly if their denominators are powers of two (1/2, 1/4, 3/8). One tenth isn't one of them. Just as 1/3 in decimal is 0.3333… forever, the Python docs show that 1/10 in binary is the endlessly repeating 0.000110011001100110011… Stop at any finite number of bits and you have an approximation.

A double keeps 53 significant bits, so the value stored for 0.1 is actually 3602879701896397 / 255, which is very slightly more than one tenth. Python would have to print 0.1000000000000000055511151231257827… to show it exactly. It doesn't: since version 3.1, Python prints the shortest decimal that maps back to the same binary value, so you see a reassuring `0.1`.

Add two slightly-off numbers and the tiny errors combine. The result lands on a different double from the one nearest 0.3, and that neighbor's shortest representation is `0.30000000000000004`. The error was always there; addition just made it visible.

For the full theory, David Goldberg's classic paper, ["What Every Computer Scientist Should Know About Floating-Point Arithmetic,"](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) is hosted by Oracle and still the standard reference.

## The fix

Wrong: ~~if (total === 0.3)~~

Right: if (Math.abs(total - 0.3) < tolerance)

Why: Floats are approximations. Compare them with a tolerance, not exact equality.

**1. Compare with a tolerance.** In Python, use `math.isclose(0.1 + 0.2, 0.3)`, which the docs recommend for comparing inexact values. In JavaScript, `Number.EPSILON` (2-52) works as a threshold for numbers around 1, but MDN warns it is inappropriate for larger magnitudes, where you need a tolerance scaled to your values.

**2. Use decimal arithmetic for money.** Python's [`decimal` module](https://docs.python.org/3/library/decimal.html) notes that in decimal floating point, `0.1 + 0.1 + 0.1 - 0.3` is exactly zero, while binary floating point gives about 5.55e-17, and "for this reason, decimal is preferred in accounting applications." Build decimals from strings (`Decimal("0.1")`), not floats, or you import the error. A common alternative in any language is to store money as integer cents.

**3. Round only for display.** Formatting a result to two decimal places is fine for showing it to a human. Rounding before comparing doesn't fix the problem: the Python docs show that `round(0.1, 1) + round(0.1, 1) + round(0.1, 1) == round(0.3, 1)` is still `False`.

## Where it bites

Shopping-cart totals that are off by a cent, loops like `for (x = 0; x != 1; x += 0.1)` that never terminate, test assertions that fail on one machine's output, and financial reports that don't reconcile. Each one starts with an `==` on a float.

>

Rule of thumb: small whole numbers are exact in a double; decimals typed into code usually aren't. If a value represents money or must match exactly, keep it out of binary floats.

## Sources

1. [Python docs: Floating-Point Arithmetic: Issues and Limitations](https://docs.python.org/3/tutorial/floatingpoint.html)
2. [MDN: Number.EPSILON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON)
3. [IEEE SA: IEEE 754-2019, Standard for Floating-Point Arithmetic](https://standards.ieee.org/ieee/754/6210/)
4. [Python docs: decimal — Decimal fixed-point and floating-point arithmetic](https://docs.python.org/3/library/decimal.html)
5. [Oracle: What Every Computer Scientist Should Know About Floating-Point Arithmetic (Goldberg)](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)

## Go deeper

- https://erroneo.us/developers/javascript-errors/
- https://erroneo.us/developers/python-errors/
- https://erroneo.us/developers/famous-software-bugs/

---
Source page: https://erroneo.us/daily/floating-point-0-1-plus-0-2/ · More: https://erroneo.us/llms.txt
