在python中的整数平方根

python中或标准库中是否有整数平方根? 我希望它是确切的(即返回一个整数),如果没有解决方案,就会吠叫。

目前我推出了自己的天真版:

def isqrt(n):
    i = int(math.sqrt(n) + 0.5)
    if i**2 == n:
        return i
    raise ValueError('input was not a perfect square')

但它很丑,我不太相信大整数。 如果我超过了这个值,我可以遍历这些方块并放弃,但我认为这样做会有点慢。 另外我想我可能会重新发明轮子,像这样的东西一定存在于Python中......


牛顿的方法在整数上运作得非常好:

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

这将返回x * x不超过n的最大整数x。 如果你想检查结果是否恰好是平方根,只需执行乘法来检查n是否是一个完美的正方形。

我在我的博客上讨论这个算法,以及另外三种计算平方根的算法。


对不起,很迟才回复; 我偶然发现了这个页面。 如果有人在将来访问此页面,python模块gmpy2被设计用于处理非常大的输入,并且包括整数平方根函数。

例:

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

当然,一切都会有“mpz”标签,但是mpz与int的标签兼容:

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

>>> int(gmpy2.mpz(12))
12

请参阅我的其他答案,讨论此方法相对于此问题的其他答案的性能。

下载:https://code.google.com/p/gmpy/


长手平方根算法

事实证明,有一种计算平方根的算法,可以通过手工计算,例如长分类。 该算法的每次迭代都会生成所产生的平方根的一个数字,同时会消耗您寻找的平方根的两位数字。 虽然算法的“长手”版本是用十进制指定的,但它可以在任何基础上工作,二进制最简单,也许执行得最快(取决于底层的bignum表示)。

由于此算法对数字逐位进行操作,因此它可以为任意大的完美平方生成精确的结果,对于非完美平方,可以根据需要生成精确度(在小数点右侧)的位数。

在“Dr. Math”网站上有两个很好的文字说明算法:

  • 二进制中的平方根
  • Longhand广场根
  • 以下是Python中的一个实现:

    def exact_sqrt(x):
        """Calculate the square root of an arbitrarily large integer. 
    
        The result of exact_sqrt(x) is a tuple (a, r) such that a**2 + r = x, where
        a is the largest integer such that a**2 <= x, and r is the "remainder".  If
        x is a perfect square, then r will be zero.
    
        The algorithm used is the "long-hand square root" algorithm, as described at
        http://mathforum.org/library/drmath/view/52656.html
    
        Tobin Fricke 2014-04-23
        Max Planck Institute for Gravitational Physics
        Hannover, Germany
        """
    
        N = 0   # Problem so far
        a = 0   # Solution so far
    
        # We'll process the number two bits at a time, starting at the MSB
        L = x.bit_length()
        L += (L % 2)          # Round up to the next even number
    
        for i in xrange(L, -1, -1):
    
            # Get the next group of two bits
            n = (x >> (2*i)) & 0b11
    
            # Check whether we can reduce the remainder
            if ((N - a*a) << 2) + n >= (a<<2) + 1:
                b = 1
            else:
                b = 0
    
            a = (a << 1) | b   # Concatenate the next bit of the solution
            N = (N << 2) | n   # Concatenate the next bit of the problem
    
        return (a, N-a*a)
    

    您可以轻松修改此函数以执行额外的迭代来计算平方根的小数部分。 我最感兴趣的是计算大型完美广场的根源。

    我不确定这与“整数牛顿法”算法相比如何。 我怀疑牛顿的方法更快,因为它原则上可以在一次迭代中生成多位解,而“长手”算法每次迭代只生成一位解。

    源回购:https://gist.github.com/tobin/11233492

    链接地址: http://www.djcxy.com/p/86635.html

    上一篇: Integer square root in python

    下一篇: How to calc square root in python?