In your Python terminal try executing this
Weird is it not? The answer should have been
True. Every programmer would have faced this issue at some point in time. If they have not, they are bound to face it in the future. As to the question ‘Why is this happening?’, first, we must understand how floating point numbers are represented inside a computer.
This is not a bug in Python or any language as a matter of fact. It is caused by an inconsistency between the different number systems. Read on for a further explanation.
First: What are floating-point numbers?
Floating-point numbers represent fractional numbers (fractions in short and are used in most engineering and technical calculations. For example,
0.0036 are floating-point numbers. Thus
0.1 can be expressed in its fractional form as
2/10. When we take the sum of these two fractions we get,
3/10 which is
Fairly straightforward is it not? That is because we use
base-10 or the
decimal number system for everyday calculations. The
base-10 number system uses numbers from
9 for representations and calculations. Thus
0.1 + 0.2 = 0.3. When it comes to computers, they understand higher-level programming languages like Python, Java, C, by converting them and storing them in the
base-2 number system or the
binary number system that comprises
Base-10 vs Base-2: The showdown!
1/3 in decimal. The decimal is a recursive fraction that goes
0.66666666. Taking the sum of the two we get
1. Since the base of the decimal system is
10, only fractions with denominators containing either of the prime factors of
10 which are
5 can be represented precisely. Similarly, only fractions with denominators containing only a prime factor of
2, which is
2 itself can be represented precisely in the binary system. Unfortunately for most decimal numbers, there is no precise representation in the binary number system.
1/10 is an infinitely repeating fraction
0.0001100110011001100110011001100110011001100110011.... The same is the case for
2/10 which is
0.001100110011001100110011001100110011.... Stopping at any finite number results in an approximation. On most machines today, floats are approximated using the IEEE double-precision floating-point standard representation which uses
64 bits for representations.
The first bit is the sign bit, S, the next 11 bits are the exponent bits, E, and the final 52 bits are the fraction F. Accordingly the closest decimal value of the truncated value
0.1 would be
0.1000000000000000055511151231257827021181583404541015625 which is close to
0.1 but not exactly equal. Similarly, for
0.2 it is
Most programming languages return
0.30000000000000004 as the sum of
0.2. But interestingly enough you can see that
0.200000000000000011102230246251565404236316680908203125 is not equal to
0.30000000000000004. This is because when a machine adds
0.2 it only sees the truncated binary values of
0.2. And the best approximation to the sum of these two binary numbers is, unsurprisingly, a value just above
But wait there’s more!
These approximation errors creep up when you try to round numbers too! You would expect rounding
2.675 to two places after the decimal point would return
2.68. But no! It returns
2.675 converted to a binary floating-point number is again replaced with a binary approximation, whose exact value is
2.67499999999999982236431605997495353221893310546875 which is closer to
A solution in Python
When working with decimal calculations what is considered to be a good practice is to always round the decimals to the number of positions of your programming requirement. In scenarios where it matters which way the decimals are rounded or the accuracy of floating-point arithmetic, Python has a module named
Unless you are handling projects which determine flight paths or the integrity of a nuclear power plant or processing the financial information of companies, floating-point approximations are not that big of an issue. When you do floating-point calculations in your language, it is wise to be mindful rather than oblivious about these.
You might also like
How to write an upgradeable ERC721 smart contract ?
Prerequisites ERC721 is a standard for non-fungible tokens (NFTs) on the Ethereum blockchain. Non-fungible tokens are unique digital assets that cannot be exchanged for other tokens or…
Code Splitting in React
Occasionally, you might encounter a situation where your application takes a while to load initially. Usually, this happens due to the size of JS files…