Integer square root in python Integer square root in python python python

Integer square root in python


Newton's method works perfectly well on integers:

def isqrt(n):    x = n    y = (x + 1) // 2    while y < x:        x = y        y = (x + n // x) // 2    return x

This returns the largest integer x for which x * x does not exceed n. If you want to check if the result is exactly the square root, simply perform the multiplication to check if n is a perfect square.

I discuss this algorithm, and three other algorithms for calculating square roots, at my blog.


Update: Python 3.8 has a math.isqrt function in the standard library!

I benchmarked every (correct) function here on both small (0…222) and large (250001) inputs. The clear winners in both cases are gmpy2.isqrt suggested by mathmandan in first place, followed by Python 3.8’s math.isqrt in second, followed by the ActiveState recipe linked by NPE in third. The ActiveState recipe has a bunch of divisions that can be replaced by shifts, which makes it a bit faster (but still behind the native functions):

def isqrt(n):    if n > 0:        x = 1 << (n.bit_length() + 1 >> 1)        while True:            y = (x + n // x) >> 1            if y >= x:                return x            x = y    elif n == 0:        return 0    else:        raise ValueError("square root not defined for negative numbers")

Benchmark results:

(* Since gmpy2.isqrt returns a gmpy2.mpz object, which behaves mostly but not exactly like an int, you may need to convert it back to an int for some uses.)


Sorry for the very late response; I just stumbled onto this page. In case anyone visits this page in the future, the python module gmpy2 is designed to work with very large inputs, and includes among other things an integer square root function.

Example:

>>> import gmpy2>>> gmpy2.isqrt((10**100+1)**2)mpz(10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001L)>>> gmpy2.isqrt((10**100+1)**2 - 1)mpz(10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L)

Granted, everything will have the "mpz" tag, but mpz's are compatible with int's:

>>> gmpy2.mpz(3)*4mpz(12)>>> int(gmpy2.mpz(12))12

See my other answer for a discussion of this method's performance relative to some other answers to this question.

Download: https://code.google.com/p/gmpy/