Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exactness of integer square root in Python

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

like image 507
zeycus Avatar asked Sep 26 '22 15:09

zeycus


1 Answers

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
like image 103
David Hammen Avatar answered Oct 13 '22 23:10

David Hammen