Search

Why Floating Point Math Gives You 0.1 + 0.2 = 0.30000000000000004

The short answer

Type 0.1 + 0.2 into almost any programming language and you get 0.30000000000000004. It is not a bug in your language.

Quick answer: Computers store most fractional numbers in binary floating point, following the IEEE 754 standard. Just as 1/3 cannot be written exactly in decimal (0.3333...), the values 0.1 and 0.2 cannot be written exactly in binary. The computer stores the nearest values it can represent, which are very slightly off. Adding them produces a result that is very slightly different from the nearest representation of 0.3, and when the language prints it, the difference shows.

The site 0.30000000000000004.com lists how dozens of languages display this same sum.

The decimal analogy

In base 10, a fraction has a finite expansion only if its denominator is built from the prime factors of 10, which are 2 and 5. So 1/2, 1/4 and 1/5 are fine, but 1/3 is 0.333... forever.

Binary is base 2, so only fractions whose denominator is a power of 2 terminate:

FractionDecimalBinary
1/20.50.1
1/40.250.01
1/80.1250.001
1/100.10.000110011001100110011... (repeats forever)

One tenth is a repeating fraction in binary. With a finite number of bits, it has to be cut off and rounded.

How a float is stored

The most common type, a 64-bit double, has three parts, much like scientific notation:

PartBitsPurpose
Sign1Positive or negative
Exponent11Where the binary point goes (the scale)
Significand (mantissa)52The significant digits

That gives roughly 15 to 17 significant decimal digits of precision. A 32-bit float has about 7.

What the computer actually stores for 0.1 is:

0.1000000000000000055511151231257827021181583404541015625

It is the closest representable value, and most languages print it as 0.1 because that is the shortest decimal that identifies it. As the Python documentation puts it, this is in the nature of binary floating point, not a fault of any particular language.

Where the extra 4 comes from

  • Stored 0.1 is slightly above one tenth.
  • Stored 0.2 is slightly above two tenths.
  • Their exact sum falls between two representable values and is rounded to the nearer one.
  • That value happens to be the next representable number above the one closest to 0.3.

So the sum and the literal 0.3 are two different, adjacent doubles. Printing enough digits to tell them apart gives 0.30000000000000004.

Other surprises from the same cause

>>> 0.1 + 0.2 == 0.3
False
>>> sum([0.1] * 10) == 1.0
False
>>> 9007199254740993.0
9007199254740992.0
>>> 0.1 + 0.2 + 0.3 == 0.3 + 0.2 + 0.1
False
  • Equality fails. Two calculations that should match can differ in the last bit.
  • Errors accumulate. Each operation may add a tiny rounding error.
  • Large integers lose precision. Above 2^53, a double cannot represent every whole number. JavaScript's Number.MAX_SAFE_INTEGER marks that limit. This is why large database IDs sent as JSON numbers can be silently corrupted, and are often sent as strings.
  • Order matters. Floating point addition is not associative.

There are also special values:

  • Infinity and -Infinity from overflow or dividing by zero.
  • NaN ("not a number") from invalid operations like 0/0. NaN is not equal to anything, including itself.
  • Negative zero, which equals zero but has a sign bit.

How to handle it

Compare with a tolerance

Never test floats for exact equality after arithmetic. Check that they are close enough:

import math
math.isclose(0.1 + 0.2, 0.3)   # True
Math.abs(a - b) < Number.EPSILON * Math.max(1, Math.abs(a), Math.abs(b))

Use integers for money

Never store currency in a float. Either store the smallest unit as an integer (cents, pence), or use a decimal type:

LanguageExact decimal option
Pythondecimal.Decimal
JavaBigDecimal
C#decimal
JavaScriptIntegers in minor units, BigInt, or a decimal library
SQLDECIMAL / NUMERIC

Small rounding errors in financial code add up to real discrepancies. Payment systems have enough ways to go wrong already; see how payment systems avoid charging you twice.

Round when displaying, not when storing

Keep full precision in calculations and format to the needed number of decimal places only for output.

Be careful summing many values

When adding many numbers of very different sizes, small ones can be lost. Sorting from smallest to largest, or using a compensated algorithm such as Kahan summation (Python's math.fsum), helps.

Why not just use decimal everywhere?

Binary floating point is implemented directly in CPU hardware, so it is extremely fast and uses a fixed, small amount of memory. It covers an enormous range, from subatomic scales to astronomical ones. For physics, graphics, statistics and machine learning, a relative error around one part in ten quadrillion is irrelevant.

Decimal types are exact for decimal fractions but slower, and they still cannot represent 1/3 exactly. No finite format can represent every real number. The right question is which errors you can tolerate.

Floating point belongs to a family of topics where the computer's representation does not quite match human expectations, alongside text encoding and dates and time zones.

Frequently asked questions

Is this a bug in JavaScript or Python?

No. Every language using IEEE 754 doubles gives the same result. Some hide it by rounding when printing.

How do I make 0.1 + 0.2 equal 0.3?

Use a decimal type, work in integers (1 + 2 tenths), or compare with a tolerance instead of ==.

Is a double more accurate than a float?

Yes. A double has about 15 to 17 significant decimal digits; a 32-bit float has about 7. Both have the same kind of rounding behaviour.

Why does NaN not equal itself?

The standard defines it that way so that invalid results never accidentally compare as equal. Use isNaN or math.isnan to test for it.

Conclusion

Floating point numbers are binary approximations with a fixed number of digits. Most decimal fractions cannot be stored exactly, so tiny errors are normal and expected. Compare with a tolerance, keep money in integers or decimals, and format only at the edges, and floating point will do exactly what it was designed to do.

Related articles

Sources and further reading

Usama Muneer

Usama Muneer

Coder, Blogger, Tech Speaker & Web Technologies Enthusiast. Passionate about working on open-source Programming languages & Tools while utilizing my Product Development skills.

Your experience on this site will be improved by allowing cookies Cookie Policy