NumPy: Round array elements (np.round, np.around, np.rint)

Posted: | Tags: Python, NumPy

You can round the elements in a NumPy array (ndarray) to a specified number of digits using np.round(). Note that it uses bankers' rounding, which means it rounds half to even (e.g., 0.5 rounds to 0.0).

For more information on rounding down and up decimals (floor and ceiling), refer to the following article.

The NumPy version used in this article is as follows. Note that functionality may vary between versions.

import numpy as np

print(np.__version__)
# 1.26.1

How to use np.round()

Basic usage

np.round() returns a new ndarray with each element of the specified array rounded. By default, it rounds to 0 decimal places.

a = np.array([12.3, 45.6, 78.9])

print(np.round(a))
# [12. 46. 79.]

print(np.round(a).dtype)
# float64

The returned ndarray maintains the same data type (dtype) as the original. For example, if the original array is of type float, the rounded array will also be float, regardless of the number of decimal places.

To convert the result to an integer (int), use astype() after np.round(). Using astype() directly to convert float to int results in truncation of decimals, effectively rounding down towards zero.

print(np.round(a).astype(int))
# [12 46 79]

print(a.astype(int))
# [12 45 78]

Array-like objects such as lists can also be specified, but an ndarray is returned.

l = [12.3, 45.6, 78.9]

print(np.round(l))
# [12. 46. 79.]

print(type(np.round(l)))
# <class 'numpy.ndarray'>

You can also specify a scalar value.

print(np.round(12.3))
# 12.0

Number of digits to round: decimals

You can specify the number of digits to round to in the second argument, decimals. The default is decimals=0.

Positive decimals values round to the specified number of decimal places, while negative values round to the corresponding integer places (e.g., -1 for tens, -2 for hundreds).

print(np.round(123.456))
# 123.0

print(np.round(123.456, 2))
# 123.46

print(np.round(123.456, -2))
# 100.0

For integers, specifying a negative decimals value rounds to the specified place. Specifying 0 or a positive value makes no change, and the returned type remains an integer (int).

print(np.round(123456))
# 123456

print(np.round(123456, 2))
# 123456

print(np.round(123456, -2))
# 123500

a = np.array([12345, 67890])

print(np.round(a, -3))
# [12000 68000]

print(np.round(a, -3).dtype)
# int64

np.round() rounds half to even (bankers' rounding)

np.round() uses bankers' rounding, which means it rounds half to even. For example, 0.5 and 2.5 are rounded to 0.0 and 2.0, respectively.

print(np.round([-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5]))
# [-4. -2. -2. -0.  0.  2.  2.  4.]

print(np.round([-350, -250, -150, -50, 50, 150, 250, 350], -2))
# [-400 -200 -200    0    0  200  200  400]

Rounding to even occurs only when the fraction is exactly 0.5; for example, 2.5 is rounded to 2.0, but 2.51 is rounded to 3.0.

print(np.round([2.49, 2.5, 2.51]))
# [2. 2. 3.]

print(np.round([249, 250, 251], -2))
# [200 200 300]

Difference between np.round() and Python's Built-in round() Function

Python's built-in round() function can also be used to round values.

While both np.round() and round() round half to even, they may produce different results for certain values.

print(np.round(0.15, 1))
# 0.2

print(round(0.15, 1))
# 0.1

While np.round() may appear more accurate, it uses a fast but sometimes inexact algorithm as noted in the official documentation.

np.round uses a fast but sometimes inexact algorithm to round floating-point datatypes. For positive decimals it is equivalent to np.true_divide(np.rint(a * 10**decimals), 10**decimals), which has error due to the inexact representation of decimal fractions in the IEEE floating point standard and errors introduced when scaling by powers of ten. numpy.round — NumPy v1.26 Manual

np.true_divide() corresponds to the / operator. np.rint() is discussed later.

For example, increasing the number of display digits shows that 0.15 is actually 0.14999.... Since the fraction is less than 0.05, it should be rounded to 0.1.

print(f'{0.15:.20}')
# 0.14999999999999999445

Other examples are also given in the official documentation.

print(np.round(56294995342131.5, 3))
# 56294995342131.51

print(round(56294995342131.5, 3))
# 56294995342131.5

If you need to process values precisely, use Python's built-in round() function or the standard library's decimal module.

np.around() and ndarray.round()

np.around() is an alias for np.round(), with identical usage.

a = np.array([12.3, 45.6, 78.9])

print(np.around(a))
# [12. 46. 79.]

print(np.around(a, -1))
# [10. 50. 80.]

Additionally, the round() method is defined as a method of ndarray.

print(a.round())
# [12. 46. 79.]

print(a.round(-1))
# [10. 50. 80.]

Custom functions for standard rounding (rounding half up)

You can define a custom function for standard rounding (rounding half up) instead of rounding half to even, as done by np.round() as follows.

After adjusting the number to the desired decimal place, 0.5 is added. Then, np.floor() is applied to truncate the decimal places, effectively rounding down towards negative infinity. Finally, the number is readjusted to its original decimal place.

def my_round(x, decimals=0):
    return np.floor(x * 10**decimals + 0.5) / 10**decimals

a = np.array([-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5])

print(np.round(a))
# [-4. -2. -2. -0.  0.  2.  2.  4.]

print(my_round(a))
# [-3. -2. -1.  0.  1.  2.  3.  4.]

print(a / 10)
# [-0.35 -0.25 -0.15 -0.05  0.05  0.15  0.25  0.35]

print(np.round(a / 10, 1))
# [-0.4 -0.2 -0.2 -0.   0.   0.2  0.2  0.4]

print(my_round(a / 10, 1))
# [-0.3 -0.2 -0.1  0.   0.1  0.2  0.3  0.4]

In the above function, -0.5 is rounded to 0.0. To round -0.5 to -1.0, you can use np.abs() to calculate the absolute value and np.sign() to restore the original sign.

def my_round2(x, decimals=0):
    return np.sign(x) * np.floor(np.abs(x) * 10**decimals + 0.5) / 10**decimals

print(a)
# [-3.5 -2.5 -1.5 -0.5  0.5  1.5  2.5  3.5]

print(my_round(a))
# [-3. -2. -1.  0.  1.  2.  3.  4.]

print(my_round2(a))
# [-4. -3. -2. -1.  1.  2.  3.  4.]

print(a / 10)
# [-0.35 -0.25 -0.15 -0.05  0.05  0.15  0.25  0.35]

print(my_round(a / 10, 1))
# [-0.3 -0.2 -0.1  0.   0.1  0.2  0.3  0.4]

print(my_round2(a / 10, 1))
# [-0.4 -0.3 -0.2 -0.1  0.1  0.2  0.3  0.4]

np.rint() for rounding to integers

np.rint() is also available for rounding to integers. It performs a process equivalent to np.round() with decimals=0.

You can specify ndarray, lists, other array-like objects, and scalar values.

a = np.array([12.3, 45.6, 78.9])

print(np.rint(a))
# [12. 46. 79.]

l = [12.3, 45.6, 78.9]

print(np.rint(l))
# [12. 46. 79.]

print(np.rint(12.3))
# 12.0

Although named rint, this function does not convert to integer (int), but rather returns an ndarray of the same type as the input.

print(np.rint(a).dtype)
# float64

Similar to np.round(), np.rint() also rounds half to even.

print(np.rint([-3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5]))
# [-4. -2. -2. -0.  0.  2.  2.  4.]

Related Categories

Related Articles