Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3 rounding behavior in Python 2

Tags:

In Python 2.x, the built-in round has the following behavior:

if two multiples are equally close, rounding is done away from 0 (so. for example, round(0.5) is 1.0 and round(-0.5) is -1.0)

In Python 3.x, this has changed to the more common:

if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2).

Is there an easy way to get this behavior in Python 2.x? Unfortunately, the future_builtins module doesn't include this. Maybe there's another similar module I haven't found yet? Or, another way to pull Python 3.x functions into Python 2.x?

Obviously, I could write a new function that produces the desired behavior, but I'm more curious if a solution exists that uses the actual Python 3.x function, to avoid adding unnecessary complexity and code to maintain.

like image 471
ford Avatar asked Feb 17 '14 20:02

ford


People also ask

How do you round numbers in Python 2?

Python's Built-in round() Function Python has a built-in round() function that takes two numeric arguments, n and ndigits , and returns the number n rounded to ndigits . The ndigits argument defaults to zero, so leaving it out results in a number rounded to an integer.

Does Python 3 round up or down?

Python has three ways to turn a floating-point value into a whole (integer) number: The built-in round() function rounds values up and down. The math. floor() function rounds down to the next full integer.

How do you control rounding in Python?

Python Programming offers a built-in round() function which rounds off a number to the given number of digits and makes rounding of numbers easier. The function round() accepts two numeric arguments, n and n digits and then returns the number n after rounding it to ndigits.

How do you round off 3 digit numbers in Python?

round() is a built-in function in Python. It returns x rounded to n digits from the decimal point.


2 Answers

Unless you mind a numpy dependency, numpy.around may do the thing:

>>> from numpy import around >>> around(0.5) 0 >>> around(-0.5) -0 >>> around(1.5) 2.0 
like image 59
bereal Avatar answered Oct 26 '22 22:10

bereal


Python 3 round in Python 2

The function can look like this:

def py3round(f):     if abs(round(f)-f) == 0.5:         return 2.0*round(f/2.0);     return round(f)  # Python 3            apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ... >>> ' '.join(map(str, map(int, [round(i * 0.25) for i in range(-20, 20)]))) '-5 -5 -4 -4 -4 -4 -4 -3 -3 -3 -2 -2 -2 -2 -2 -1 -1 -1 0 0 0 0 0 1 1 1 2 2 2 2 2 3 3 3 4 4 4 4 4 5' # Python 2            apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ... >>> ' '.join(map(str, map(int, [py3round(i * 0.25) for i in range(-20, 20)]))) '-5 -5 -4 -4 -4 -4 -4 -3 -3 -3 -2 -2 -2 -2 -2 -1 -1 -1 0 0 0 0 0 1 1 1 2 2 2 2 2 3 3 3 4 4 4 4 4 5' 

Let me clarify what round does in bltinmodule.c

if hasattr(args[0], '__round__'):     return args[0].__round__(*args[1:]) else:      raise TypeError("type %.100s doesn't define __round__ method") 

So round actually does almost nothing. It depends on the objects passed to it. That leads to floatobject.c function static PyObject *double_round(double x, int ndigits)

z = round(y); if (fabs(y-z) == 0.5)     /* halfway between two integers; use round-half-even */     z = 2.0*round(y/2.0); 

I used the knowledge of these lines in my function above.

Python 2 round in Python 3

I think you need to write a new function.

def python2round(f):     if round(f + 1) - round(f) != 1:         return f + abs(f) / f * 0.5     return round(f) 

The if statement handles the case that i + 0.5 and i + 1.5 are rounded into different directions = to even numbers and halves. In this case the rounding is done away from zero.

# in Python 2          apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ... >>> ' '.join(map(str, map(int, [round(i * 0.25) for i in range(-20, 20)]))) '-5 -5 -5 -4 -4 -4 -4 -3 -3 -3 -3 -2 -2 -2 -2 -1 -1 -1 -1 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5' # in Python 3          apply round to ... -.1 -.75 -.5 -.25 0 .25 .5 .75 ... >>> ' '.join(map(str, map(int, [python2round(i * 0.25) for i in range(-20, 20)]))) '-5 -5 -5 -4 -4 -4 -4 -3 -3 -3 -3 -2 -2 -2 -2 -1 -1 -1 -1 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5' 

Do you need a solution with the second argument to round, ndigits?

like image 24
User Avatar answered Oct 26 '22 20:10

User