 ## Introduction

The Python `math` module contains several functions that allow you to perform various mathematical calculations on real numbers. One of those functions is `floor()`, which returns the largest integer not greater than its argument. The Python floor() function is part of the standard library, meaning it comes prepackaged with every installation of Python and is ready to be used immediately.

In this article, you'll take a closer look at the Python floor() function and gain a solid understanding of what values you can expect it to return.

## Overview of the Python floor() Function

The Python `floor()` function performs a calculation similar to that of rounding down. Given a number, floor() will return the largest integer value less than or equal to that same number. For example:

``````>>> import math
>>> math.floor(6.253)
6
``````

Here, you pass the float 6.253 into the Python floor() function, which returns the integer value 6.

Note that you first had to import the `math` module in order to access the floor() function. While floor() is a part of the standard library, you have to explicitly tell Python that you want to be able to use this function. `import math` accomplishes this step.

However, typing `math.floor(number)` can get pretty tiresome. You can modify the import statement to where you only need to call floor() in the interpreter:

``````>>> from math import floor
>>> floor(7.79)
7
``````

Here, you've told the interpreter to specifically load the Python floor() function from the `math` module. Now, you can simply call `floor(number)` instead of having to prepend `math.` to each function call.

NOTE: Later in this article, you'll use special constants from the `math` module - like `math.e` and `math.pi` - to demonstrate the functionality of floor(). To ensure you can run such examples, be sure to include the call `import math` in your interpreter.

## Flooring Numbers

Most of us are familiar with the concept of rounding down. It's the process by which we take a number with digits after the decimal place and figure out which whole number we should use to represent it instead.

Rounding in Python will return the next closest integer to a given number. For instance, the number 7.4 would round down to 7, as it's only four "steps" away from 7 but six "steps" away from 8. In contrast, 7.6 would round up to 8.

This rule, however, invites a conundrum with numbers like 7.5, which is equally far apart from both 7 and 8. In these cases of rounding, Python 3 will then choose the closest even integer to the given number. In other words, 7.5 would round up to 8, but 6.5 would round down to 6:

``````>>> round(7.4) # closer to 7; round down
7
>>> round(7.6) # closer to 8; round up
8
>>> round(7.5) # choose closest even integer: round up to 8
8
>>> round(6.5) # choose closest even integer: round down to 6
6
``````

This may be different from what you know to do by hand (and in Python 2), which is to round up for any number whose ending digit is 5. Note that in Python 2 the `round()` function returns a float, whereas in Python 3 it returns an integer.

Flooring numbers, on the other hand, is a bit simpler. When you're flooring numbers, you don't have to worry about choosing the closest integer or looking for an even number. Instead, you only need to consider the number that comes before the decimal point. This is the floor of that number: the largest integer less than or equal to a given number.

Here's how the examples from the previous code block work when you floor the numbers instead of round them:

``````>>> # closer to 7, but 7 is still largest integer <= 7.4
>>> floor(7.4)
7
>>> # closer to 8, but 7 is still largest integer <= 7.6
>>> floor(7.6)
7
>>> # equidistant between 7 and 8, but 7 is still largest integer <= 7.5
>>> floor(7.5)
7
>>> # exactly equal to 7, and 7 is still largest integer <= 7
>>> floor(7)
7
``````

In each instance, the number 7 is returned as the floor, as it is always the largest integer less than or equal to the given number.

## Flooring Negative Numbers

At this time in Python 3, the Python floor() function might just be seen as another way to convert a float to an integer by truncating any numbers after the decimal. In that case, why not just use `int()`? To answer this question, let's take a slight detour and talk about the weather.

Weather widgets are extremely common applications. Chances are you have one running on your device right now. Having an accurate idea of what the weather will be like on any given day is a crucial part of planning for many industries, from construction to travel and beyond.

Let's say that following the freak winter storm that hit the US state of Texas in mid-February 2021, you've been hired by an energy company to develop a weather dashboard in Python. The company sends you a list of temperatures each day and would like them to be rounded down to the next lowest whole degree. Their goal is to develop a freeze warning alert system that will notify customers when temperatures drop below freezing.

If you stick with round() or even int(), then you'll quickly find out that your code won't quite meet the specifications stated by the client. For example, here's what these two functions return when the temperature drops below zero degrees Celsius:

``````>>> round(-0.4)
0
>>> int(-0.4)
0
``````

int() truncates the number you pass to it, moving the value closer to 0. In this case, it removes the decimal point and the number that follows it, leaving -0 which simply resolves to 0. Similarly, round() sees that -0.4 is only four "steps" away from 0 (compared to the six steps it is away from -1) and returns 0 as well.

However, your client has asked you to round all temperatures "down to the next lowest whole degree." This means that a temperature value of -0.4 should return -1, not 0.

In fact, the Python floor() function is the answer to this problem:

``````>>> floor(-0.4)
-1
``````

Here, floor() looks for the next lowest whole integer that is less than or equal to -0.4. The largest integer that is less than -0.4 is -1, and the Python floor() function correctly returns this value.

The Python floor() function is what you would want to use in order to correctly process the numbers for the energy company's freeze warning alert dashboard. That's because, as soon as temperatures start to drop below zero (`[-0.1, -0.2, -0.3, ...]`), the app will send the proper notification, as floor() will round these temperatures down to -1. Had you used round() or int() instead, then the app would experience a delay, with temperatures ranging from -0.1 to -0.9 degrees without any notification being sent. As we've seen in Texas in February 2021, early warnings are critical when it comes to freezing temperatures. The Python floor() function will ensure you're returning the right value every time.

## Flooring Constants in Python 2 vs Python 3

The Python standard library also contains several numeric constants that can be accessed through the `math` module. These include:

``````>>> math.pi # pi: ratio of a circle's circumference to its diameter
3.141592653589793
>>> math.e # e: base of the natural logarithm
2.718281828459045
>>> math.tau # tau: ratio of a circle's circumference to its radius, equal to 2?
6.283185307179586
>>> math.inf # floating-point positive infinity
inf
>>> -math.inf # floating-point negative infinity
-inf
>>> math.nan # not a number
nan
``````

Many of these constants have only existed as part of the `math` module since Python 3. `math.inf` and `math.nan` were added in Python 3.5, while `math.tau` was included from Python 3.6 and onwards. Previously, the values `inf` and `nan` could only be created by passing a string to `float()`.

The changes to how these numbers are represented in Python has also changed how they respond to being passed as arguments into the Python floor() function. These changes will give you an understanding of how the floor() function has changed from Python 2 to 3. Let's take a look at each of them in turn, and compare their return values in Python 2 vs Python 3.

## `math.pi`

Both Python 2 and Python 3 contain the constant `math.pi`, but the values returned are of different types:

``````>>> # Python 2
>>> floor(math.pi)
3.0
>>>
>>> # Python 3
>>> floor(math.pi)
3
``````

In Python 2, `floor(math.pi)` returns a `float` value, whereas in Python 3, an `int` value is returned. In general, the Python 2 floor() function returns float values, whereas the Python 3 floor() function returns integer values. This makes sense, as the core functionality of floor() is returning the next lowest integer for a given number.

### `math.e`

The constant `math.e` is present in both Python 2 and Python 3:

``````>>> # Python 2
>>> floor(math.e)
2.0
>>>
>>> # Python 3
>>> floor(math.e)
2
``````

Again, the Python 2 floor() function returns the float 2.0 whereas the Python 3 floor() function returns the integer 2.

### `math.tau`

The constant `math.tau` does not exist in Python 2:

``````>>> # Python 2
>>> floor(math.tau)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'tau'
``````

However, mathematically the constant tau is equal to two times the constant pi. Thus, tau can be represented by simply multiplying `math.pi` by two and passing the result into the Python floor() function:

``````>>> # Python 2
>>> floor(2*math.pi)
6.0
>>>
>>> # Python 3
>>> floor(math.tau)
6
``````

Note that `math.tau` does exist as a constant in Python 3, and the Python 3 floor() function has no trouble returning the correct value.

## `math.inf` and `-math.inf`

The concept of infinity can bring some interesting and potentially unexpected return values in Python, no matter which version you're running. To complicate things, the Python floor() function wants to return the largest integer less than or equal to a given number. How can this work with infinity?

Let's start with seeing how Python 2 and Python 3 represent the concept of infinity:

``````>>> # Python 2
>>> math.inf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'inf'
>>>
>>> float('inf')
inf
>>>
>>> # Python 3
>>> math.inf
inf
``````

As you can see, `math.inf` was explicitly added as a constant for Python version 3.5 and up. In Python 2, you can access an infinite value by passing the string `'inf'` to `float()`.

However, Python 2 is the version that actually returns a floored value for infinity with no error:

``````>>> # Python 2
>>> floor(float('inf'))
inf
>>>
>>> # Python 3
>>> floor(math.inf)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
``````

Interestingly, Python 2 actually returns a value when flooring infinity, whereas Python 3 raises an `OverflowError`. This updated functionality makes more sense: the Python floor() function is meant to return the next lowest integer less than or equal to the number you gave it. What number is less than or equal to infinity? The question has no answer: all numbers are less than infinity, and infinity cannot equal itself.

Both versions of Python behave similarly to the previous example when trying to floor negative infinity:

``````>>> # Python 2
>>> floor(-float('inf'))
-inf
>>>
>>> # Python 3
>>> floor(-math.inf)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
``````

Infinity, by definition, cannot be represented as an integer. Since the Python floor() function looks for the next lowest and largest integer, it should - in theory - be unable to return a result for either negative or positive infinity. Newer versions of Python, such as 3.5 and above, successfully takes this mathematical conundrum into account by raising an `OverflowError` when trying to call the Python floor() function on an infinite value.

### `math.nan`

The last constant we'll consider here is `math.nan`. This is a special data type that stands for not a number (NaN). In other words, the returned value is either not defined, unrepresentable, or missing.

As you saw in the previous section, Python 2 is relatively consistent about returning a value from `float()`, even if that value might not make mathematical sense. The same pattern can be seen in its treatment of `nan`:

``````>>> # Python 2
>>> floor(float('nan'))
nan
>>>
>>> # Python 3
>>> floor(math.nan)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: cannot convert float NaN to integer
``````

Here, Python 2 simply returns the passed-in argument `nan` as its own floor. However, Python 3 takes the mathematical complexity of NaN into consideration and instead raises a `ValueError`, which states that the float `nan` cannot be converted to an integer for flooring. Indeed, this should be the case, as any value that is "not a number" should indeed not be able to be converted to a numeric type, as the value does not exist.

## Understanding Floor Division

The Python floor() function can be used for one additional mathematical calculation, and that is to find the floor of a division expression.

The result of a division operation generally has two parts: the quotient and the remainder. The quotient is the part of the result that shows how many times one number goes into another. For example, the expression `12 / 5` results in the value 2.4:

``````>>> 12 / 5
2.4
``````

5 goes into 12 two full times, and this is represented by the 2 in front of the decimal point. From there, the remainder is the amount we have left over. Since `5 * 2` is only 10, we still need two more numbers to reach 12. So, the remainder is 2. This remainder can be represented as a decimal point by dividing it by the divisor, which is 5. `2 / 5` simplifies to 0.4, and this is the .4 from the expression above.

Recall that the process of flooring a number seeks to return the next lowest and largest integer to the given number. This concept can be combined with general division to perform what's called floor division.

In floor division, there is no remainder returned in the final value. Instead, the division is performed, and then the Python floor() function returns the floor of the result:

``````>>> 12 / 5
2.4
>>> floor(12 / 5) # 2 is largest integer <= 2.4
2
``````

Here, you can see that the Python floor() function returns the largest integer lower than or equal to the result of the original division. The result is the same when dividing negative integers:

``````>>> floor(-12 / 5) # -3 is largest integer <= -2.4
-3
``````

You can also use the double slash operator `//` to perform floor division in Python, instead of calling the Python floor() function directly:

``````>>> 12 // 5
2
>>> -12 // 5
-3
``````

Here, the floor division operator `//` returns the same values as the Python floor() function.

## Conclusion

In this article, you took a closer look at the Python floor() function to see what values it returns and how this has changed from Python 2 to Python 3.

You've examined the differences between floor(), int(), and round(), and considered a scenario in which the Python floor() function is the superior choice. You've seen how to floor positive numbers, negative numbers, and special constants defined in the `math` module. Lastly, you took a quick look at floor division and learned how to use the floor division operator.

The Python floor() function is part of the Python standard library, and is likely one of those functions you'll come across early on in your Python learning journey. If you're interested in learning more about the basics of coding and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article! If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.