Edxz
Edxz

Reputation: 823

Python rounding incorrect result

I want to round number in python but it keep giving me the inaccurate result for example I want to round 99.999999946 into 99.99, or 56.3633333 into 56.36 this is what I've tried:

int(99.999999946*100)/100   #result = 99
int(99.999999946*100)/100.0 #result = 99.989999999999995
round(99.999999946, 2)      #result = 100.0

thanks before

Upvotes: 2

Views: 2876

Answers (3)

mirandes
mirandes

Reputation: 967

This allows you to round to the desired number of decimal places.

def round_decimal(dec, places=2):
    return int((dec * 10**places) + 0.5) / 10.**places

Upvotes: 0

Tim Peters
Tim Peters

Reputation: 70592

Until you get comfortable with limitations of binary floating point, you'll probably be much happier with the decimal module, which implements a rich decimal floating-point model. Among other things, it allows fine control over rounding modes:

>>> import decimal
>>> d = decimal.Decimal("99.999999946")
>>> print d
99.999999946
>>> chopped = d.quantize(decimal.Decimal(".01"), decimal.ROUND_DOWN)
>>> print chopped
99.99

Generalizing

Here's a function that will chop to any digit position you like, and returning a float too (which is, in general, inexact!):

def chop_to_n_decimals(x, n):
    # This "rounds towards 0".  The decimal module
    # offers many other rounding modes - see the docs.
    import decimal
    d = decimal.Decimal(repr(x))
    targetdigit = decimal.Decimal("1e%d" % -n)
    chopped = d.quantize(targetdigit, decimal.ROUND_DOWN)
    return float(chopped)

For example,

for x in 5555.5555, -5555.5555:
    for n in range(-3, 4):
        print x, n, "->", chop_to_n_decimals(x, n)

displays:

5555.5555 -3 -> 5000.0
5555.5555 -2 -> 5500.0
5555.5555 -1 -> 5550.0
5555.5555 0 -> 5555.0
5555.5555 1 -> 5555.5
5555.5555 2 -> 5555.55
5555.5555 3 -> 5555.555
-5555.5555 -3 -> -5000.0
-5555.5555 -2 -> -5500.0
-5555.5555 -1 -> -5550.0
-5555.5555 0 -> -5555.0
-5555.5555 1 -> -5555.5
-5555.5555 2 -> -5555.55
-5555.5555 3 -> -5555.555

Upvotes: 3

phihag
phihag

Reputation: 287835

All the results are correct. int rounds down, whereas round rounds to the nearest number (i.e. digits 0-4 get rounded down, 5-9 up for positive numbers). In Python 2.x, / with integer arguments is integer division unless you import division from __future__, and integer division rounds down as well.

int(99.999999946*100)/100 gets evaluated as

int(99.999999946*100)/100
int(9999.9999946) / 100
9999 / 100 # int rounds down
99         # integer division rounds down

The division in int(99.999999946*100)/100.0 is a float one. The result may not be precisely 99.98, but that's to be expected since 0.98 = 48 / 50 cannot be expressed in base 2.

int(99.999999946*100)/100.0
int(9999.9999946) / 100.
9999 / 100.0        # int rounds down
99.989999999999995  # floating-point division

For your last example, note the digit at the second decimal place

round(99.999999946, 2) = 100.0
round(99.989999999999995, 2) = 99.99

If you want correct (but rather slow) decimal calculation, use the decimal module:

import decimal
d = decimal.Decimal('99.999999946')
d.quantize(decimal.Decimal('.01'), decimal.DOWN)  # Decimal('99.99')

Upvotes: 2

Related Questions