I am using Python 2.0. I tried doing -9/4 and was expecting the answer to be -2. However, it returns -3. Now -9/4 is -2.25 and I thought int type would round it up to -2 instead of -3. When I do int(-2.25), it returns -2. Can anyone please explain why int(-9/4) returns -3 but int(-2.25) returns -2?
The two operations simply have different rounding modes. From the int() documentation, (reference)
If x is floating point, the conversion truncates towards zero.
Whereas division rounds down, (reference)
Plain or long integer division yields an integer of the same type; the result is that of mathematical division with the ‘floor’ function applied to the result.
Related
This question already has answers here:
Why is math.sqrt() incorrect for large numbers?
(4 answers)
Is floating point math broken?
(31 answers)
Closed 5 years ago.
If you take a number, take its square root, drop the decimal, and then raise it to the second power, the result should always be less than or equal to the original number.
This seems to hold true in python until you try it on 99999999999999975425 for some reason.
import math
def check(n):
assert math.pow(math.floor(math.sqrt(n)), 2) <= n
check(99999999999999975424) # No exception.
check(99999999999999975425) # Throws AssertionError.
It looks like math.pow(math.floor(math.sqrt(99999999999999975425)), 2) returns 1e+20.
I assume this has something to do with the way we store values in python... something related to floating point arithmetic, but I can't reason about specifically how that affects this case.
The problem is not really about sqrt or pow, the problem is you're using numbers larger than floating point can represent precisely. Standard IEEE 64 bit floating point arithmetic can't represent every integer value beyond 52 bits (plus one sign bit).
Try just converting your inputs to float and back again:
>>> int(float(99999999999999975424))
99999999999999967232
>>> int(float(99999999999999975425))
99999999999999983616
As you can see, the representable value skipped by 16384. The first step in math.sqrt is converting to float (C double), and at that moment, your value increased by enough to ruin the end result.
Short version: float can't represent large integers precisely. Use decimal if you need greater precision. Or if you don't care about the fractional component, as of 3.8, you can use math.isqrt, which works entirely in integer space (so you never experience precision loss, only the round down loss you expect), giving you the guarantee you're looking for, that the result is "the greatest integer a such that a² ≤ n".
Unlike Evan Rose's (now-deleted) answer claims, this is not due to an epsilon value in the sqrt algorithm.
Most math module functions cast their inputs to float, and math.sqrt is one of them.
99999999999999975425 cannot be represented as a float. For this input, the cast produces a float with exact numeric value 99999999999999983616, which repr shows as 9.999999999999998e+19:
>>> float(99999999999999975425)
9.999999999999998e+19
>>> int(_)
99999999999999983616L
The closest float to the square root of this number is 10000000000.0, and that's what math.sqrt returns.
In my application I encountered the following and was surprised by the results:
8/-7=-2 (both integers).
What does this mean?
For the actual values, i.e. 8.0/(-7.0), the result is roughly -1.143.
Your result using integer division is being rounded down toward the more negative value of -2. (This is also known as "Floor division")
This is why you will get the somewhat perplexing answers of:
>>> 8/(-7)
-2
>>> 8/7
1
Note: This is "fixed" in Python 3, where the result of 8/(-7) would be -1.143. So if you have no reason to be using Python 2, you should upgrade. ;)
In Python 3, if you still want integer division, you can use the // operator. This will give you the same answer as 8/(-7) would in Python 2.
Here's a Python Enhancement Proposal on the subject: PEP 238 -- Changing the Division Operator
Python always does the "floor division" for both negative numbers division and positive numbers division.
That is
1/10 = 0
1/-10 = -1
But sometime we need 1/-10 to be 0
I figure out it can be done by using the float division first then cast result to int, e.g.
int(float(1)/-10) = 0
That works fine for me, no need to import the future division or upgrade to Python 3
Hope it can help you~
To have Python automatically convert integer division to float, you can use:
from __future__ import division
Now:
8/-7=-1.1428571428571428
This feature is not in the standard Python 2 not to break existing code that relied on integer division.
However, this is the default behavior for Python 3.
When both values are integers when dividing Python uses Floor division.
In Python, / operator is for integer division. You can look at it as float division followed by a floor operation.
For example,
8/7 == floor(8.0/7.0) == 1
8/-7 == floor(8.0/-7.0) == -2
If I run python on my terminal and type this, and hit enter:
-1 / 2
It returns
-1
If I do the same in XCode, compiling C++ code, and I have this:
int idx = -1 / 2;
cout << idx << endl;
It prints this:
0
Why are these rounding differently?
EDIT :forgot to mention that 'int' is an integer type (int). This is corrected.
In Python integer division has always rounded downwards, as if you used the floor function.
In C++03 the rounding direction was left to the compiler.
In C++11 and later it is required to be towards zero.
As I see it, the C++ rounding direction is more easy to understand for novices, since it gives the same kind of numerical result that you would calculate by hand. It also corresponds to how most computers implement integer division, i.e. is efficient at the level of individual operations. The Python rounding direction, on the other hand, is mathematically more elegant and more practically useful in programming.
One practical difference, illustrating the Pythonic elegance, is to compute how many cabs with capacity of 3 passengers you need for a party of 10 persons. In Python, -(-10//3). In C++, (10 + (3-1))/3.
Because that's how integer division specified in those languages (downwards vs. zerowards).
Python will round any division between integers downwards (i.e. the smallest of the two integers between the real decimal value). If the result is 2.6, it will round to 2, and if it's -2.6 it will round to -3.
C++ will round towards zero (whether the result is positive or negative). So if the result is 2.6 it will be rounded to 2, and if it's -2.6 it will be rounded to -2.
This question already has answers here:
Negative integer division surprising result
(5 answers)
Closed 8 years ago.
Just randomly tried out this:
>>> int(-1/2)
-1
>>> int(-0.5)
0
why the results are different??
Try this:
>>> -1/2
-1
>>> -0.5
-0.5
The difference is that integer division (the former) results in an integer in some versions of Python, instead of a float like the second number is. You're using int on two different numbers, so you'll get different results. If you specify floats first, you'll see the difference disappear.
>>> -1.0/2.0
-0.5
>>> int(-1.0/2.0)
0
>>> int(-0.5)
0
The difference you see is due to how rounding works in Python. The int() function truncates to zero, as noted in the docs:
If x is floating point, the conversion truncates towards zero.
On the other hand, when both operands are integers, the / acts as though a mathematical floor operation was applied:
Plain or long integer division yields an integer of the same type; the result is that of mathematical division with the ‘floor’ function applied to the result.
So, in your first case, -1 / 2 results, theoretically, in -0.5, but because both operands are ints, Python essentially floors the result, which makes it -1. int(-1) is -1, of course. In your second example, int is applied directly to -0.5, a float, and so int truncates towards 0, resulting in 0.
(This is true of Python 2.x, which I suspect you are using.)
This is a result of two things:
Python 2.x does integer division when you divide two integers;
Python uses "Floored" division for negative numbers.
Negative integer division surprising result
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
Force at least one number to float, and the results will no longer surprise you.
assert int(-1.0/2) == 0
As others have noted, in Python 3.x the default for division of integers is to promote the result to float if there would be a nonzero remainder from the division.
As TheSoundDefense mentioned, it depends upon the version. In Python 3.3.2:
>>> int(-1/2)
0
>>> int(-0.5)
0
int() command truncates towards 0, unlike floor() which rounds downwards to the next integer.
So int(-0.5) is clearly 0.
As for -1/2, actually -1/2 is equal to -1! Therefore rounding downwards to the next integer is -1. In Python 2, -a/b != -(a/b). Actually, -1/2 equals floor(-1.0 / 2.0), which is -1.
I am trying to find the cause of this result:
import numpy
result1 = numpy.rint(1.5)
result2 = numpy.rint(6.5)
print result
The output:
result1-> 2
result2-> 6
This is odd: result1 is correct but I result2 is not (It has to be 7 because rint rounds any float to the nearest integer).
Any idea? (THANKS!)
From numpy's documentation on numpy.around, equivalent to numpy.round, which supposedly also is relevant for numpy.rint:
For values exactly halfway between rounded decimal values, Numpy
rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, -0.5
and 0.5 round to 0.0, etc. Results may also be surprising due to the
inexact representation of decimal fractions in the IEEE floating point
standard [R9] and errors introduced when scaling by powers of ten.
Also relevant: While for large numbers there might be representation errors, for small values half integers are exactly representable in binary-base floating points, in particular 1.5 and 6.5 are exactly representable in standard single-precision floats. Without the preference for either odd, even, lower, upper integers or any other scheme one would have undefined behaviour here.
As #wim points out in the comments the behaviour of Python's build-in round is different. It rounds away from zero: It prefers upper integers for positive inputs and lower integers for negative inputs. (see http://docs.python.org/2/library/functions.html#round)
I think this is the rule of the thumb - when you have a float midway between two integers, like 1.5 lies midway between 1 and 2 and since both choices are equally good, we prefer rounding to the even number(which is 2 in this case) and for 6.5, which lies midway between 6 and 7, 6 is the closest even number.