"
This article is part of in the series

Python is considered one of the easier programming languages to learn and boasts a massive standard library. Not to mention, it supplies the flexibility to approach problems in different ways. 

Case in point: rounding a number.

There are a few different ways you can round a number in Python. In this post, we will look at four approaches, beginning with the built-in round() function.

Rounding Numbers with the round() Function

Using the round() function is one of the most straightforward ways to round a number in Python. It accepts two numeric arguments, "n" and "ndigits." 

It processes these inputs, rounding the number held in "n" to "ndigits." By default, the value of the "ndigits" argument is zero. So, if you don't give it any value, the number in "n" will turn into an integer. 

If you've handled number rounding before, there's a good chance that you approach it this way:

  1. You round the number "n" to "p" decimal places by shifting n's decimal point by p places. The value in n is multiplied by 10p to get a value "m." 
  2. You then look at the number in the m's first decimal place. Let's say this number is "d." If "d" is less than 5, you round m down; else, you round m up. 
  3. Lastly, you move the decimal point back p places by dividing m by 10p.

The algorithm is quite straightforward. Even if you don't usually approach rounding this way, you should be able to understand it. 

All it's doing is taking the last digit after the decimal point and rounding down the number if it is below 5. If it is above 5, the algorithm round it up.

Meaning if you try to round 2.5 with this algorithm, it'll round up to 3. But if you try to round 1.64 with it, it'll round down to 1.6. 

But this is not how the round() function works.

Here's what happens when you try to round 2.5 with the function. 

>>> round(2.5)
2

Surprising, right? But what happens when you try to round 1.5 with the same function?

>>> round(1.5)
2

Which isn't what you'd expect. But these outputs aren't a cause for alarm – you don't have to raise an issue on the Python bug tracker. This is because the method is designed to work this way. 

This is because Python uses the IEEE 754 standard for rounding. The approach is termed "banker's rounding," and the idea behind it is that the numbers are rounded to the nearest value with an even least significant digit.

If you don't think this rounding strategy suits your needs, there are three other ways you can round a number in Python.

Rounding Numbers by Truncating

Truncating is the simplest way of rounding numbers but is also the most primitive. The idea behind truncating is that all the digits after a given position are replaced with zero.

Value

Truncated To

Result

14. 568

Tens place

10

14. 568

Ones place

14

14. 568

Tenths place

14.5

14. 568

Hundredths place

14.56

 

Here's what the truncation algorithm does:

  1. The number you supply is multiplied by 1000. This shifts the decimal point three places to the right.
  2. The integer part of the new number is taken with int().
  3. This number is divided by 1000 to shift the decimal places back three places.

It's easy to generalize this process – all you have to do is replace "1000" with 10p, with "p" indicating the number of decimal places to truncate. 

Here's what the function will look like:

def truncate(n, decimals=0):
    multiplier = 10 ** decimals
    return int(n * multiplier) / multiplier

The second argument in this truncate() function defaults to 0. The function returns the integer part of the number passed to it if no second argument is passed.

You can use this function equally well with the positive and negative numbers:

>>> truncate(12.5)
12.0

>>> truncate(-5.963, 1)
-5.9

>>> truncate(1.625, 2)
1.62

>>> truncate(125.6, -1)
120.0

>>> truncate(-1374.25, -3)
-1000.0

You may have noticed that truncating a positive number results in rounding down. On the other hand, truncating a negative number results in it rounding up. 

If the program you're writing needs you to round up or round down numbers specifically, you can write programs for both of these applications. 

Let's explore what these rounding methods look like.

Rounding Up Numbers 

The idea of rounding up a number involves rounding it to the next higher number up to a specific number of digits. Here's a table that summarizes this:

Value

Truncated To

Result

14. 568

Tens place

20

14. 568

Ones place

15

14. 568

Tenths place

14.6

14. 568

Hundredths place

14.57

 

You can use the ceil() function in the math module to round up numbers in Python. As you might be able to guess, the name of the ceil() method is derived from the word "ceiling." 

The term ceiling in math describes the nearest integer that is greater than or equal to a given number. By the same token, the nearest integer that is lower than or equal to a given number is its floor. 

You must note that the numbers that lie between two integers are not themselves integers. More importantly, the ceiling of two intervals is the greater of the two intervals. Let's go over this concept with an example.

The number 2.2 lies between 2 and 3, making its floor 2 and its ceiling 3. You might be aware of the concept of the ceiling function, which maps every number to its ceiling. 

The function also accepts integers, mapping their ceilings to the integer itself. Python also provides a ceiling function math.ceil(), which returns the nearest integer greater than or equal to the input. 

>>> import math

>>> math.ceil(3.2)
4

>>> math.ceil(4)
4

>>> math.ceil(-0.7)
0

So, this is an excellent built-in Python function you can use to round up numbers. But you also have the option of writing your own function, like so:

def round_up(n, decimals=0):
    multiplier = 10 ** decimals
    return math.ceil(n * multiplier) / multiplier

It might seem like this round_up() function is a lot like the truncate() function. This is because their algorithms are quite similar.

It shifts the decimal point in n the right number of places to the right. This is done by multiplying n by 10 ** decimals. 

The derived value is rounded up to the nearest integer with the math.ceil() function. Then, the program shifts the decimal point to the left by dividing the value by 10 ** decimals. 

Most techniques for rounding numbers have similar steps – the decimal point is shifted, some rounding method is applied, then the decimal point is shifted back. 

This pattern of rounding numbers is so popular because it's the most obvious mental algorithm humans came up with to round numbers. 

Here are a few instances of the round-up function in action:

>>> round_up(2.1)
3.0

>>> round_up(4.23, 1)
4.3

>>> round_up(7.543, 2)
7.55

It's also worth noting that you can pass a negative value to the "decimals" part of the algorithm, as you would in truncate(). Here's how that would work:

>>> round_up(32.45, -1)
40.0

>>> round_up(1452, -2)
1500

When a negative number is passed to the function in this way, the first argument written in the function rounds it to the appropriate number of digits to the left of the decimal point.

Knowing this, does this make you curious about what passing a negative value to round_up() would do?

Let's have a look:

>>> round_up(-1.5)
-1.0

You might have expected expecting symmetry around zero when rounding numbers. This might have led you to think that just like 1.5 is rounded to 2, -1.5 must round up to -2.0.

You need to remember how the math.ceil() function works to make sense of the real result. 

It helps to remember the difference between rounding up and down. 

Visualize a number scale going from -5 to 5. Rounding up means the value jumps from left to right. In contrast, rounding down means the value jumps from right to left. 

Rounding Down Numbers

Rounding down a number is the opposite of rounding it up.

The idea of rounding down a number involves rounding it to the next lower number up to a specific number of digits.

Here's a table that summarizes this:

Value

Truncated To

Result

14. 568

Tens place

10

14. 568

Ones place

14

14. 568

Tenths place

14.5

14. 568

Hundredths place

14.56

 

Rounding a number down in Python involves more or less the same algorithm that round_up() and truncate() use. You shift the decimal point, round to an integer, and shift back the decimal point. 

The nice thing about Python is that the standard library comes with the math.floor() method, which does the opposite of what the ceil() method does. It rounds to the floor of the number in question after shifting the decimal point. 

>>> math.floor(2.2)
2

>>> math.floor(-1.5)
-2

Let's now look at how you would write the round_down() function:

def round_down(n, decimals=0):
    multiplier = 10 ** decimals
    return math.floor(n * multiplier) / multiplier

So, as you can see, the program is the same as the round_up() program, except math.ceil() has been replaced with math.floor().

Let's try putting a few different values in round_down():

>>> round_down(2.5)
2

>>> round_down(3.37, 1)
3.3

>>> round_down(-0.7)
-1

Writing a round_up() or round_down() function is an excellent way to round numbers quickly. But bear in mind that the impact on the data is extreme. 

If you use these functions in a large dataset, the dataset will likely become significantly less precise. This decrease in precision can dramatically alter computations done using the data.