Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the under-the-hood differences between round() and numpy.round()?

Let's look at the ever-shocking round statement:

>>> round(2.675, 2)
2.67

I know why round "fails"; it's because of the binary representation of 2.675:

>>> import decimal
>>> decimal.Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')

What I do not understand is: why does NumPy not fail?

>>> import numpy
>>> numpy.round(2.675, 2)
2.6800000000000002

Thinking

Do not mind the extra zeros; it's an artefact from Python's printing internal rounding. If we look at the "exact" values, they're still different:

>>> decimal.Decimal(round(2.675, 2))
Decimal('2.6699999999999999289457264239899814128875732421875')

>>> decimal.Decimal(numpy.round(2.675, 2))
Decimal('2.680000000000000159872115546022541821002960205078125')

Why oh why does NumPy behave?

I thought at first that NumPy had to handle floats using extra bits, but:

>>> decimal.Decimal(numpy.float(2.675))
Decimal('2.67499999999999982236431605997495353221893310546875')
>>> decimal.Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')
# Twins!

What is happening behind the curtains? I looked a bit at NumPy's round implementation, but I'm a Python newbie and I don't see anything overly fishy.

like image 558
LaGoutte Avatar asked Dec 04 '13 23:12

LaGoutte


People also ask

What is round in NumPy?

The numpy. round_() is a mathematical function that rounds an array to the given number of decimals. Syntax : numpy.round_(arr, decimals = 0, out = None) Parameters : array : [array_like] Input array.

How do you round numbers in NumPy Python?

To round elements of the array to the nearest integer, use the numpy. rint() method in Python Numpy. For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value. The out is a location into which the result is stored.

What is a correct method to round decimals in NumPy?

Ceil. The ceil() function rounds off decimal to nearest upper integer.

What does math round do in Python?

Python round() Function The round() function returns a floating point number that is a rounded version of the specified number, with the specified number of decimals. The default number of decimals is 0, meaning that the function will return the nearest integer.


1 Answers

One on top of the hood difference is documented:

In cases where you're halfway between numbers, np.round rounds to the nearest "even" number (after multiplying by 10**n where n is the second argument to the respective round function) whereas the builtin round rounds away from 0.

>>> np.round(2.685, 2)
2.6800000000000002
>>> round(2.685, 2)
2.69

Under the hood, you can get differences when using the scaling parameter. Consider the differences between round(2.675 * 10.**2) and round(2.675, 2). This is certainly a result of the floating point math which as always has some rounding error associated with it. To go any further we would really need to look at the real implementation.

like image 108
mgilson Avatar answered Oct 19 '22 00:10

mgilson