Python

# How to round numbers in Python

This tutorial touches upon one of basic fundamental practices – rounding numbers in Python. Rounding off is a basic yet essential mathematical function that people use to make calculations easier. Its purpose is to acquire a value near the actual value in a much simpler form.

This tutorial provides an in-depth guide on rounding numbers in Python. All you need beforehand is an IDE or an editor (we’re using VS code) and Python 3.9.0 or above.

There are many ways you might want to round off a number. Python offers a lot of methods to do it. We’re going to explore all of them below.

## Rounding VS Truncation

Rounding approximates a value to the nearest number, which simplifies calculations while preserving precision to some extent.

Meanwhile, truncation discards the digits after the number of decimal places specified without considering any conditions.

Of course, this can make a massive difference when there are minor differences in values. An example of a stock market clarifies things much more.

The Vancouver Stock Exchange (VSE) is infamous for losing 25 points every month in 1982 because they truncated values to three decimal places several times each day. Let’s consider the following code:

```import random

randomValues = [random.uniform(0.01, 0.1) for i in range(500000)]

def truncateNumber(num):

return int(num * 1000) / 1000

sumOfNumbers = 0

sumOfTruncate = 0

for n in randomValues:

sumOfNumbers = sumOfNumbers + n

sumOfTruncate = truncateNumber(sumOfTruncate + n)

print("Truncating upto 3 decimal places:")

print("Original Sum = ", sumOfNumbers)

print("Total Using Truncate = ", sumOfTruncate)

print("Difference (truncate) = ", sumOfNumbers - sumOfTruncate, '\n')

print("Using round() upto 3 decimal places:")

sumOfNumbers1 = 0

sumOfTruncate1 = 0

for n in randomValues:

sumOfNumbers1 = sumOfNumbers1 + n

sumOfTruncate1 = round(sumOfTruncate1 + n, 3)

print("Original Sum = ", sumOfNumbers1)

print("Total Using round() = ", sumOfTruncate1)

print("Difference (round()) = ", sumOfNumbers1 - sumOfTruncate1)
```  Let’s break the code down to make it more comprehensive:

1. We’ve imported the random library, using which we’ve initiated an array of random numbers between 0.01 and 0.1 using random.uniform(). These are in the range of 500,000 seconds.
2. Next, the truncate(num) function takes a value and chops off the digits after 3 decimal places.
3. We take the original sum, the sum obtained after truncating the values, and then calculate the difference.
4. We will then use round() on the same set of values and find the original sum, sum after rounding the values and the difference between both.

The output shows a significant difference between both strategies. A lot of precision is lost when we use truncate instead of round(), which could lead to substantial problems.

## Round up

Rounding up numbers in decimal form means converting them to an integer greater than that number.

It reduces the precision of your work but also makes calculation simpler. In Python, there are two ways to round up numbers:

### Rounding up using round()

The first approach anyone uses to round numbers in Python is the built-in round function – round(n, i). It takes two values as arguments; the number “n” that is to be rounded off and “i,” the number of decimal places the number needs to be rounded off to.

The second argument is optional. If you want to round up numbers, you only need to include the first argument in round(), i.e., the value on which you want to perform the function.

For decimals greater than 0.5, round() always returns the higher integer value.

For example, if you were rounding off 10.6 using round(), the Python interpreter will display 11. To make it clearer, let’s look at the code below.

```value1 = 6.925

value2 = 5.42

value3 = 9.87

round1 = round(value1)

round2 = round(value2)

round3 = round(value3)

print('Values'.ljust(20), 'Rounded Up')

print(str(value1).ljust(20), round1)

print(str(value2).ljust(20), round2)

print(str(value3).ljust(20), round3)
``` First, we assign float values to three variables value1, value2, and value3. Next, we pass them as arguments in the round() function.

Lastly, we print two columns, one with the original value and the second with the rounded-up value. You will note that the code returns 7 and 10, the higher integer values for 6.925 and 9.87.

However, for 5.42, the output is 5 because the decimal place has 0.42 – less than 0.6. This may be a problem in many areas, which is why we move on to the second method of rounding up numbers.

### Rounding up using math.ceil()

To use the ceil() function, you’ll have to import the math library. This function automatically returns the higher integer value for a decimal number.

For example, both 10.2 and 10.6 will return 11, regardless of whether the decimal is higher than 0.5 or not. See the code below:

```import math

print(math.ceil(10.2))

print(math.ceil(10.6))
``` The working of ceil() makes it much more convenient than round() for rounding up numbers.

## Round down

If you’ve learned how to round up, rounding down will be a breeze. You can go two ways about it:

### Rounding down using round()

For decimal 0.5 and less, the round() function returns the lesser integer value. For 4.2, you’ll get 4. Let’s alter the code used previously to make things clearer.

```value1 = 3.2

value2 = 4.5

value3 = 4.852

round1 = round(value1)

round2 = round(value2)

round3 = round(value3)

print('Values'.ljust(20), 'Rounded Down')

print(str(value1).ljust(20), round1)

print(str(value2).ljust(20), round2)

print(str(value3).ljust(20), round3)
``` First, we store float values in three variables. Next, we print two columns for the original and rounded values. As you can see, we get correct results for 3.2 and 4.5.

However, for a decimal number like 4.852, round() may be wrong. Another thing worth noticing is that if the decimal place has 0.5, round() will either round the value up or down, depending upon which of the two integers it lies between is even.

Hence, for 0.5, the function always returns an even number. Let’s take a look at a more convenient way to round down.

### Rounding down using math.floor()

By importing the math library into your code, you can make use of its floor() function. It automatically returns the lower value for a decimal number. Hence, for both 8.3 and 8.9, you get 8. Let’s consider the code below:

```import math

print(math.floor(8.3))

print(math.floor(8.9))
``` You can see that the output for the code gives us the exact results we want, making floor() the better alternative for rounding down desired numbers.

## Round half up or down

Both rounding half up and down refer to rounding a specified number to the closest digit to guarantee more precision.

However, in half up, the value lying between two numbers will convert to the higher number. Meanwhile, half down converts the value to the lower number.

Below, we’ve put together a code to see how round half up and down work:

```import decimal

import math

def roundHalfUp(value, decimals = 0):

multiplyWith = 10 ** decimals

return math.floor(value * multiplyWith + 0.5) / multiplyWith

def roundHalfDown(value, decimals = 0):

multiplyWith = 10 ** decimals

return math.ceil(value * multiplyWith - 0.5) / multiplyWith

print(roundHalfUp(15.28, 1))

print(roundHalfUp(15.25, 1))

print(roundHalfDown (1.5))

print(roundHalfDown(2.5, 1))
``` First, you shift the decimal point towards the right up to the places specified. Next, you determine the value of digit after the shifted decimal point.

Is greater than 5, lesser than 5, or equal to 5? The next step is to add 0.5 and apply the floor function for round half up. For round half down, you subtract 0.5 from the number and apply the math.ceil() function.

The output shows the accurately rounded half up and down values.

## Rounding float

Now that you’re well accustomed to the round() function, you can easily use it to round off float values. Previously, we left out the second optional argument for rounding up and down.

All you have to do is specify the number of digits you want to round off the number to for rounding float values. Let’s look at the code below:

```print(round(10.9258, 2))

print(round(6.9054, 1))

print(round(110.9873, 3))

print(round(2000.32537453, 4))

print(round(7.9424, 2))
``` The output shows that each float value has been rounded to the number of decimal places specified as the argument.

## Round decimal

Python offers a decimal module which allows for more precision when dealing with numbers. It was designed by considering how people do arithmetic in real life.

Therefore, it preserves significant digits, gives a more exact representation of decimals, and allows for flexible precision as per the user’s convenience. This module offers many rounding strategies:

1. ROUND_CEILING: rounded value is greater than the number
2. ROUND_DOWN: rounded values moves towards 0
3. ROUND_FLOOR: rounded value is less than the number
4. ROUND_HALF_DOWN: rounded values move halfway towards 0
5. ROUND_HALF_EVEN: rounded values move halfway to the nearest even number
6. ROUND_HALF_UP: rounded values move halfway away from 0
7. ROUND_UP: rounded values move away from 0

Let’s see the code below to observe how each of these functions work:

```import random

randomValues = [random.uniform(0.01, 0.1) for i in range(500000)]

def truncateNumber(num):

return int(num * 1000) / 1000

sumOfNumbers = 0

sumOfTruncate = 0

for n in randomValues:

sumOfNumbers = sumOfNumbers + n

sumOfTruncate = truncateNumber(sumOfTruncate + n)

print("Truncating upto 3 decimal places:")

print("Original Sum = ", sumOfNumbers)

print("Total Using Truncate = ", sumOfTruncate)

print("Difference (truncate) = ", sumOfNumbers - sumOfTruncate, '\n')

print("Using round() upto 3 decimal places:")

sumOfNumbers1 = 0

sumOfTruncate1 = 0

for n in randomValues:

sumOfNumbers1 = sumOfNumbers1 + n

sumOfTruncate1 = round(sumOfTruncate1 + n, 3)

print("Original Sum = ", sumOfNumbers1)

print("Total Using round() = ", sumOfTruncate1)

print("Difference (round()) = ", sumOfNumbers1 - sumOfTruncate1)
```  First, we import the decimal module. Next, we assign a float value to the variable round_num and then round it to 2 places and store it in final_val.

Finally, we apply all strategies for rounding off decimals. Here, quantize() plays an essential role. First, before the dot (.) operator, we specify the value to be rounded off.

Since we want to round off a decimal, we instantiate round_num as a decimal. In the brackets of .quantize(), we specify the places upto which we want to round off the decimal.

Lastly, we’ve printed the results. The output shows the differences in the result depending upon the rounding strategy used.

## Round to the nearest integer (5 or 10)

There may be a case where you want to round a value to a multiple of a specific digit. Let’s consider two bases here, 5 and 10.

We’re looking to round off a number to obtain an output that is always a multiple of either bases, i.e. 5 or 10. For example, for 14, rounding to the nearest integer being 5 should give you 15, whereas, for 10, you need 10.

Let’s look at the following code to find out how to do this:

```def myroundto5(n, base=5):

return base * round(n/base)

def myroundto10(n, base=10):

return base * round(n/base)

print(myroundto5(11))

print(myroundto5(14))

print(myroundto10(14))

print(myroundto10(21))
```  The value to be rounded off is n, while the base is 5 or 10. The base can be set as any number you wish. The next step is to divide the value with the base and round the result to obtain an integer.

Lastly, multiply this integer with your base to get its multiple as your rounded figure. The output shows how different numbers are rounded off with 5 or 10 as their base.

## Round to nearest fraction

Python also includes a fraction module. It allows numerous arithmetic calculations to be performed on fractions or rounds fractions upto desired digits. Let’s take a look at the code below:

```from fractions import Fraction

fractionValue = Fraction(50, 3)

roundedWithoutLimit = round(fractionValue)

roundedWithLimit = round(fractionValue, 2)

print('Fraction'.ljust(15), 'Round Without Limit'.ljust(20), 'Round With Limit')

print(str(fractionValue).ljust(15), str(roundedWithoutLimit).ljust(20), roundedWithLimit)
``` Make sure you import Fraction from the fractions module to use it in your code. Next, we instantiate a fraction object and assign the numerator as 50 and the denominator as 3.

Next, we perform rounding two ways. We don’t specify the number of places we want to round off the fraction and assign the value to the variable roundedWithoutLimit.

Next, we round the fraction up to 2 decimal places and assign the value to roundedWithLimit. Lastly, we print the results in three columns, where the difference between the two results is apparent.

## Round negative numbers

Now that you’ve learned about rounding positive numbers, dealing with negative numbers won’t be an issue. You can go about rounding negative numbers in three ways:

The first method is the basic built-in function present in Python i.e., round(). It works for positive and negative integers similarly.

If the decimal place is greater than 0.5, the function returns the higher integer of the two integers the value lies between.

On the other hand, if it’s less than 0.5, the round() returns the lesser integer. Remember that for 0.5, round() always returns an even integer.

So for two float values, 9.2 and 4.5, you get 9 and 4, respectively. The second method is to use math.ceil() function. Ceil is always used for rounding up values.

The float value -3.6 lies between -3 and -4. The greater integer is -3, so ceil returns that. Hence, for negative values, ceil moves downwards, as opposed to its working for positive numbers.

Thirdly, you can use math.floor() function. It is always used for rounding down values. Let’s take the same example of a float value -3. It lies between -3 and -4.

The lesser integer is -4, hence math.floor() will return that. Hence, for negative values, it moves upwards on the number scale, as opposed to its working for positive numbers.

Let’s take a look at the following code to see how Python rounds negative numbers:

```import math

value1 = -9.2

value2 = -4.5

value3 = -3.6

print('value1'.ljust(15), 'round()'.ljust(15), 'math.ceil()'.ljust(15), 'math.floor()')

print(str(value1).ljust(15), str(round(value1)).ljust(15),
str(math.ceil(value1)).ljust(15), str(math.floor(value1)))

print(str(value2).ljust(15), str(round(value2)).ljust(15),
str(math.ceil(value2)).ljust(15), str(math.floor(value2)))

print(str(value3).ljust(15), str(round(value3)).ljust(15),
str(math.ceil(value3)).ljust(15), str(math.floor(value3)))``` First, we import the math library to ensure access to ceil and floor functions. Next, we assign float values to three variables – value1, value2, and value3.

Lastly, we print 4 columns. The first one is for the negative number, which is being rounded. The other three columns are for round(), math.ceil(), math.floor() respectively.

The results show apparent differences between the strategies to round negative numbers discussed above.

## Round without round() (using divmod)

divmod(num1, num2) is a function in Python that takes a dividend and divisor as arguments and returns a tuple of quotient and remainder. We can use its working to round a number to the nearest 5 or 10. Let’s take a look at the following code:

```def roundUsingDivmod(value):

quotient, remainder = divmod(value, 5)

if remainder >= 5:

quotient += 1

return quotient * 5

print(roundUsingDivmod(105.2))
``` First, we have defined a function that takes the number to be rounded off i.e., value, as an argument. Next, we apply divmod() on value with the divisor as 5.

To round to the nearest 10, replace the second argument with 10. Next, we check if the remainder is greater than or equal to 5. If so, we add 1 in the quotient, which means we are rounding up.

Lastly, we multiply the quotient with 5 to return a multiple of 5 as the rounded answer. Finally, we pass 105.2 as the argument for this function. The result prints 105.0 as the answer, the nearest multiple of 5.

## Round NumPy array

NumPy arrays are widely used to store data in data science and scientific computing. It is a practical strategy because of its vectorization and broadcasting features.

These allow functions to be applied to the whole array at once instead of one element at a time. Make sure you have NumPy installed on your system to use NumPy arrays.

These arrays can be rounded using round() and around() functions. Let’s take a look at the following code:

```
import numpy as np

npArray = [0.323859, 3.302424, -7.3480239, 8.93483290, -0.3423423, 0.3423532]

round1 = np.round(npArray, 2)

round2 = np.around(npArray, 2)

print(round1, '\n', round2)
``` First, we import the numpy module and assign it to np. Next, we initialize a 1×6 array. Lastly, we will use the round() and around() functions and pass the array and the number of places we want to round that function upto.

Lastly, we print the results, and you can observe that both functions give the same results.