Skip to tool
ecech.
💻 Developer & Code

Floating Point Inspector That Shows the Number Your Code Actually Holds

Every language stores 0.1 as something slightly larger. See the exact value, the 64 bits, and the gap to the next number that exists.

What is actually stored

Error vs what you typed

Gap to the next double

Safe integer?

The 64 bits

Arithmetic with this number

Advertisement

How the calculation works

The bug that is not a bug (1.005).toFixed(2) → "1.00" Every developer reads this as a rounding bug. It is not. what is stored 1.00499999999999989... the 1.005 you typed does not exist as a double Rounding correctly rounds DOWN, because the value really is below the halfway point.

How to Use This Tool

Type any number. You get the exact value stored in memory, the bits, and how far it is from the number you meant.

The expansion always terminates

A double stores a binary fraction, and every binary fraction is a sum of powers of two, so its decimal form is finite. It is just long. 0.1 is stored as exactly:

0.1000000000000000055511151231257827021181583404541015625

That is not an approximation of the stored value — it is the stored value, written out. Your language prints 0.1 because it prints the shortest string that reads back to the same double, which is a display convenience and not the number.

The example that actually changes how you code

0.1 + 0.2 is famous and inert. This one is not:

(1.005).toFixed(2) returns "1.00", not "1.01".

It looks like toFixed is broken. It is not. 1.005 cannot be stored exactly, and the nearest double is 1.00499999999999989341858963598497211933135986328125 — genuinely below the halfway point. Rounding it down is correct. Every currency bug of the shape “the total is a cent off” is some version of this.

It is not one unlucky number, either. 2.675 rounds to 2.67, 0.615 to 0.61 and 1.255 to 1.25, all for the same reason: each is stored just below the value you typed. Try them in the box above and read the long number.

Doubles are not evenly spaced near 1 gap 2.2e-16 near 2⁵⁰ near 2⁵⁰⁰ The bigger the number, the wider the gap. Past 2⁵⁰ consecutive integers stop being representable.
Precision is relative, not absolute. That is what the exponent buys you.

What to do about it

  • Money: use integers. Store cents, not pounds. Every language that gets currency right does this, and every one that does not has a rounding bug waiting.
  • Comparison: use a tolerance. Math.abs(a - b) < 1e-9 rather than a === b. Pick the tolerance from the size of your numbers, not from a blog post.
  • Integers: watch 2⁵⁰. Above Number.MAX_SAFE_INTEGER (9,007,199,254,740,991) consecutive integers are no longer all representable, so a 64-bit database ID loses digits silently in JSON. Send it as a string.
  • Accumulating: order matters. Adding a million small numbers to a large one loses more than adding the small ones together first.

This is not a JavaScript problem

It applies to double in C, Java, C#, Go, Rust, Swift and to Python's float — all the same IEEE 754 binary64. Python's decimal, Java's BigDecimal and similar types avoid it by storing decimal digits instead, at a cost in speed. JavaScript gets blamed because it has no integer type to fall back on.

Advertisement

Frequently Asked Questions

Why is 0.1 + 0.2 not 0.3?
Because neither 0.1 nor 0.2 can be stored exactly in binary, the same way one third cannot be written exactly in decimal. Each is stored as the nearest available double, and the two small errors add up to something just past 0.3. The sum is 0.30000000000000004, which is a real number your computer is genuinely holding.
Why does (1.005).toFixed(2) give 1.00?
Because 1.005 is not what is stored. The nearest double is 1.00499999999999989341858963598497211933135986328125, which is below the halfway point, so rounding down is correct. This looks like a bug in toFixed and is really the value having been rounded once already, when you typed it.
How should I handle money then?
Store integers — cents rather than pounds, and divide only when displaying. Every system that handles currency correctly does this. If you need decimal fractions with exact arithmetic, use a decimal type such as Python's decimal or Java's BigDecimal, which stores decimal digits rather than binary ones.
What is Number.MAX_SAFE_INTEGER?
9,007,199,254,740,991, or 2^53 − 1. Below it, every integer has an exact double. Above it, the gap between representable numbers exceeds 1, so consecutive integers start being skipped. This is why 64-bit database IDs must travel through JSON as strings — parse them as numbers and the last digits change silently.
Is this only a JavaScript problem?
No. It is IEEE 754 binary64, which is the double type in C, Java, C#, Go, Rust and Swift, and Python's float. JavaScript takes the blame because it has no separate integer type, so the behaviour surfaces in ordinary code rather than only where a developer chose a float.
Does my input go anywhere?
No. The bit inspection and the exact expansion are computed in your browser using the same IEEE 754 arithmetic your code uses.

Related tools in Developer & Code

Browse all Developer & Code tools
A handwritten note reading ecech.com resting on the keyboard used to build the site.

Made by one person

ecech. is not a content farm. Every tool here is written and checked by hand, one at a time, by someone who wanted the tool to exist and could not find a version that showed its working.

No accounts and no sign-in, and nothing you type reaches a server — every calculation on this page runs inside your browser. The ads are served by Google and do set their own cookies, which is set out in full on the privacy page. More about the site.