views:

207

answers:

5

Why Does -22/10 return -3 in python. Any pointers regarding this will be helpful for me.

+10  A: 

Because it's integer division by default. And integer division is rounded towards minus infinity. Take a look:

>>> -22/10
-3
>>> -22/10.0
-2.2000000000000002

Positive:

>>> 22/10
2
>>> 22/10.0
2.2000000000000002

Regarding the seeming "inaccuracy" of floating point, this is a great article to read: Why are floating point calculations so inaccurate?

Eli Bendersky
Why are the floating point calculations so inaccurate? Are there any documents regarding this?
Chaitanya
updated to answer your comment
Eli Bendersky
If more precision is required, take a look at http://docs.python.org/library/decimal.html the Python decimal module.
SapphireSun
+2  A: 

Because you're doing an integer division. If you do -22.0/10 instead, you'll get the correct result.

Can Berk Güder
+5  A: 

By default, the current versions of Python 2.x (I'm not sure about 3.x) give an integer result for any arithmetic operator when both operands are integers. However, there is a way to change this behaviour.

from __future__ import division
print(22/10)

Outputs

2.2000000000000002

Of course, a simpler way is to simply make one of the operands a float as described by the previous two answers.

Chinmay Kanchi
+5  A: 

PEP 238, "Changing the Division Operator", explains the issues well, I think. In brief: when Python was designed it adopted the "truncating" meaning for / between integers, simply because most other programming languages did ever since the first FORTRAN compiler was launched in 1957 (all-uppercase language name and all;-). (One widespread language that didn't adopt this meaning, using / to produce a floating point result and div for truncation, was Pascal).

In 2001 it was decided that this choice was not optimal (to quote the PEP, "This makes expressions expecting float or complex results error-prone when integers are not expected but possible as inputs"), and to switch to using a new operator // to request division with truncation, and change the meaning of / to produce a float result ("true division").

You can explicitly request this behavior by putting the statement

from __future__ import division

at the start of a module (the command-line switch -Q to the python interpreter can also control the behavior of division). Missing such an "import from the future" (and command line switch use), Python 2.x, for all values of x, always uses "classic division" (i.e., / is truncating between ints).

Python 3, however, always uses "true division" (/ between ints produces a float).

Note a curious corollary (in Python 3)...:

>>> from fractions import Fraction
>>> Fraction(1/2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/fractions.py", line 100, in __new__
    raise TypeError("argument should be a string "
TypeError: argument should be a string or a Rational instance

since / produces a float, it's not acceptable as the argument to Fraction (otherwise precision might be silently lost). You must use a string, or pass numerator and denominator as separate arguments:

>>> Fraction(1, 2)
Fraction(1, 2)
>>> Fraction('1/2')
Fraction(1, 2)

gmpy uses a different, more tolerant approach to building mpqs, its equivalent of Python 3 Fractions...:

>>> import gmpy
>>> gmpy.mpq(1/2)
mpq(1,2)

Specifically (see lines 3168 and following in the source), gmpy uses a Stern-Brocot tree to get the "best practical approximation" of the floating point argument as a rational (of course, this can mask a loss of precision).

Alex Martelli
+1  A: 

This happens because the operation of integer division returns the number, which when multiplied by the divisor gives the largest possible integer that is no larger than the number you divided.

This is exactly why 22/10 gives 2: 10*2=20, which is the largest integer multiple of 10 not bigger than 20.

When this goes to the negative, your operation becomes -22/10. Your result is -3. Applying the same logic as in the previous case, we see that 10*-3=-30, which is the largest integer multiple of 10 not bigger than -20.

This is why you get a slightly unexpected answer when dealing with negative numbers.

Hope that helps

inspectorG4dget