How to compute the nth root of a very big integer

后端 未结 10 651
暖寄归人
暖寄归人 2020-12-01 06:28

I need a way to compute the nth root of a long integer in Python.

I tried pow(m, 1.0/n), but it doesn\'t work:

OverflowError: lo

10条回答
  •  广开言路
    2020-12-01 07:15

    You can make it run slightly faster by avoiding the while loops in favor of setting low to 10 ** (len(str(x)) / n) and high to low * 10. Probably better is to replace the len(str(x)) with the bitwise length and using a bit shift. Based on my tests, I estimate a 5% speedup from the first and a 25% speedup from the second. If the ints are big enough, this might matter (and the speedups may vary). Don't trust my code without testing it carefully. I did some basic testing but may have missed an edge case. Also, these speedups vary with the number chosen.

    If the actual data you're using is much bigger than what you posted here, this change may be worthwhile.

    from timeit import Timer
    
    def find_invpow(x,n):
        """Finds the integer component of the n'th root of x,
        an integer such that y ** n <= x < (y + 1) ** n.
        """
        high = 1
        while high ** n < x:
            high *= 2
        low = high/2
        while low < high:
            mid = (low + high) // 2
            if low < mid and mid**n < x:
                low = mid
            elif high > mid and mid**n > x:
                high = mid
            else:
                return mid
        return mid + 1
    
    def find_invpowAlt(x,n):
        """Finds the integer component of the n'th root of x,
        an integer such that y ** n <= x < (y + 1) ** n.
        """
        low = 10 ** (len(str(x)) / n)
        high = low * 10
    
        while low < high:
            mid = (low + high) // 2
            if low < mid and mid**n < x:
                low = mid
            elif high > mid and mid**n > x:
                high = mid
            else:
                return mid
        return mid + 1
    
    x = 237734537465873465
    n = 5
    tests = 10000
    
    print "Norm", Timer('find_invpow(x,n)', 'from __main__ import find_invpow, x,n').timeit(number=tests)
    print "Alt", Timer('find_invpowAlt(x,n)', 'from __main__ import find_invpowAlt, x,n').timeit(number=tests)
    

    Norm 0.626754999161

    Alt 0.566340923309

提交回复
热议问题