Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default rounding mode in python, and how to specify it to another one?

What is the default rounding mode (rounding to nearest, etc) in Python? And how can we specify it?

like image 975
zell Avatar asked Dec 01 '15 21:12

zell


People also ask

How do you specify rounding in Python?

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 round up or down by default?

By default, it rounds a number to the nearest whole number. We'll also see how to use the function's parameters to change the type of result returned to us. We'll then talk about the math. ceil() and math.


2 Answers

With IEEE754-based platform (as most modern ones do, including x86, ARM, MIPS...), it's default mode "round to nearest, ties to even" is the only mode available in Python standard library. That is "provided" by standardized defaults and absense of library methods to change it. There are more languages that doesn't allow to change rounding mode - e.g. Java - so this isn't an isolated Python whim.

In real, there are too few reasons to change this. Direct rounding modes of IEEE754 are very special in their use. (I don't apologize the approach to stick on the default rounding, but simply comment on it.) For example, multiply of 1e308 by 1e308 with rounding to zero or to minus infinity results in approximately 1.8e308, so, the result is too far both from the exact answer and from POLA-based one (infinity). If you really need some specific modes for your computations, consider using specific libraries, like MPFR or gmpy2.

If you insist on changing this without external modules specialized on floating-point calculations, try using C-library fesetround via ctypes module or analog, e.g. here. Again, it's your choice to use such hacks and become responsible to all consequences. I'd suggest wrapping all pieces with special rounding to C-level code which restores the default mode on function exit.

like image 139
Netch Avatar answered Sep 19 '22 11:09

Netch


The accepted answer is not really correct. While floats are probably what first comes to mind when someone asks about rounding modes, they are not the place you should look.

The reason is simple: rounding is something you use to make your answer have a smaller number of digits. Whenever you mention digits, you must be sure what base you're talking about. I don't know about you specifically, but when people speak of digits, they usually mean decimal digits. For that purpose, floats are obviously inadequate, since they have binary digits. You cannot round a float 0.12 to one decimal digit because it doesn't make sense: despite the appearance, it doesn't have that kind of digits. :-)

Of course, what you can do, is try to compensate for the decimal inexactness of floats by rounding them so the overshoots and undershoots cancel each other in the best possible way, and in that context, it has been proven long ago that there is only one right answer, ROUND_HALF_EVEN---and it is provided by float (and by round function, if you need it on some higher decimal place) out of the box. But please note that it's not the same as 'calculating the mean grade' (ROUND_HALF_UP, usually), or 'estimating the mean error' (ROUND_UP), or 'giving you a tax grade (ROUND_FLOOR), or various other specific tasks which need some fixed number of decimal digits (or in case of some now defunct currencies, some other base, but usually not binary).

And in fact, there is a Python standard library module which gives you all the rounding modes you might find useful, and given the above paragraphs, it is the logical place to look: of course, it's the decimal module. It represents floating point numbers not in base 2, but in base 10, and as such, it offers the meaningful possibility to round a number to a given number of decimals, using a rounding method that makes sense for a particular task.

>>> import statistics, decimal
>>> grades = map(decimal.Decimal, [4, 5])
>>> print(statistics.mean(grades).to_integral_exact(decimal.ROUND_HALF_UP))
5

HTH.

like image 33
Veky Avatar answered Sep 18 '22 11:09

Veky