Be careful when using Python’s floor division

Using Python has a lot of advantages. For example, you can install (nearly) flawlessly a huge amount of packages using the integrated pip package manager, there are a lot of integrated packages that solve a lot of problems out-of-the-box, it provides a powerful language that is yet easy to use.

Like everything in this world, even though it has a lot of advantages, it has a lot of problems too. The biggest issue that I am facing while writing Python programs (that is a big amount of my time!) is when I have to deal with arithmetics, and in particular floating point operations.

In the beginning of my pythonic journey, that drove me mad! I think I have spent countless hours debugging arithmetic errors. But now I understood the basic rule: never ever (ever) do a floating point operation without using numpy. The only times I am not using it is for use cases where having approximated numbers can be acceptable, for example when performing the sum of randomly generated values that are used to compute a simulation (DES) delay. As soon as I will never have to compare those values, and by definition they are an approximation, it still does the work.

Problem

You knew that 1 divided by 0.1 does 9? No? I didn’t know, too. Try to execute the following code in your beloved Python interpreter to double check:

1 // 0.1

It is important to notice that Python is technically right! It is 9 because the 0.1 value is approximated with a value that is “a little more” than 0.1. So, being 0.1 “a little more” than 0.1, it does not fit into 1 ten times, but nine instead.

That said, even though the computer never lies, I guess that no one in the world would like to have a conceptually wrong but theoretically right result.

Solution

There are a few solutions to this problem. The first is using the built-in math function, using the division operator wrapped inside the floor function to save you the issue to install one more package.

from math import floor

floor(1 / 0.1)

Another solution, that is the recommended one, is to use numpy. I recommend this solution because if you have to deal with floating point numbers, you can fall into this kind of problems a lot of times in your code. Wrapping every arithmetic operation in some numpy’s functions will allow you to keep a good peace of mind.

import numpy

numpy.floor(1 / 0.1)

My two cents

This might look like a trivial post, but I assure you it is not. The solution is just using a function, nothing fancy, but the debugging time spent on this type of problems is just huge.

My opinion is that, when you are using floating point numbers, you should choose the desired precision and then keep it, no matter what. Then, if you have to use some arithmetic functions, try to use the ones provided by numpy. This will save you a lot of headaches.

For example you can end up using something like that:

import numpy

def operation(value):
    return numpy.float64(numpy.round(value, 6))

numpy.floor(operation(1 / 0.1))

Conclusions

I love Python, for real, but I hate the way it handles floating point operations. When you start using this language for the first time you are really surprised the first time something like that shows up, but the more time passes and more you get used to. I hope you learned something new today. If you want to become an expert of regex, reading some examples telling you how to use them with Python, I think you should definitely check out this article.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Website Built with WordPress.com.

Up ↑

%d bloggers like this: