I have these two values that needed to round to two decimal spaces
n = 59.9250
n1 = 459.4250
print(round(n, 2))
print(round(n1, 2))
output
59.92
459.43
can someone explain why and there is a way to round both the same way I'm using python version 3.6.8
Python uses IEEE-754 double precision numbers for the built-in floating point objects, meaning that the vast majority of numbers cannot be represented exactly. You can test this experimentally by creating a variable just below and above the limit:
>>> n3 = 1e308 ; n3
1e+308
>>> n3 = 1e309 ; n3
inf
But, since CPython is open source, you can also verify this by looking at the code which handles floating point objects. In CPython, it can be found in Objects/floatobject.c
and you'll see that code peppered with C double
variables to hold the values.
So, if you type those two numbers into a conversion site such as this binary converter, you will see they convert into the closest matches as follows:
|
59.925 59.92499999.....something
459.925 459.42500000..1..something
|
You can see there that, following the rule "next digit of 0..4
rounds down, while 5..9
rounds up", the first one will round down to 59.92
because the next digit is 4
(keeping in mind that no special "half-way" behaviour comes into play here because neither is exactly half-way).
For the same reason, the second one will round up to 459.93
because its next digit is 5
.
The Python documentation for round
actually calls out this possibility:
Note: The behavior of
round()
for floats can be surprising: for example,round(2.675, 2)
gives2.67
instead of the expected2.68
. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.
If you really want to avoid this issue, you should be skipping the use of the built-in floating point objects with all their foibles, and instead opt for using the Decimal
class.
You can then manipulate numbers in a great many ways with that while avoiding loss of precision. For example, the following transcript:
ROUND_HALF_UP
specifier) rather than using banker's rounding; then>>> d = decimal.Decimal("59.925")
>>> decimal.getcontext().rounding = decimal.ROUND_HALF_UP
>>> round(d, 2)
Decimal('59.93')