I would like to understand why something is happening. I needed to implement the integer square root in Python (isqrt(64) = 8 = isqrt(80)). I was convinced that the naive approach:
def isqrt(n):
return int(math.sqrt(n))
was bound to fail occasionally when the n passed is a square number, assuming that Python converts to floats, then performs a square root calculation on floats. For instance, calling isqrt(13*13) I expected that after converting to floats and calculating sqrt, you could get something like 12.999999843, which after casting to integer would give us 12.
But I performed large loops testing values, big and small, and always get the correct result. It would seem there is no need to implement a special square root for integers, after all!
Not understanding bothers me, as much as when something that was supposed to work is failing. Why is this happening?
There is another question regarding integer square root in python: Integer square root in python
In the isqrt() defined there, a +0.5 is added to n, which I guess was included precisely to fight the issue I mentioned I was expecting, but cannot find in a specific case.
EDIT: Forgot to specify, I am using Python 2.7
Using python 2.7 on a machine with the C type long
as a 64 bit integer and C type double
implemented as a 64 bit IEEE floating point number yields
>>> import math
>>> x = (2<<53) + 1
>>> int(math.sqrt(x*x)) == x
False
I cheated and chose a number that 64 bit IEEE floating point can't represent exactly (but python's integer type can), (2<<53) + 1
. Python 2.7 computes x*x
as a python 2.7 long
integer. (Note: This is distinct from a C long
; python 2.7 can represent 2<<600
as an integer, but C cannot.)
Speaking of 2<<600
,
>>> import math
>>> x = 2<<600
>>> int(math.sqrt(x*x)) == x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to float
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With