How to find integer nth roots?

后端 未结 11 1455
醉酒成梦
醉酒成梦 2020-12-01 16:22

I want to find the greatest integer less than or equal to the kth root of n. I tried

int(n**(1/k))

But for n=125, k=3 this gives the wrong

相关标签:
11条回答
  • 2020-12-01 17:00

    How about:

    def nth_root(val, n):
        ret = int(val**(1./n))
        return ret + 1 if (ret + 1) ** n == val else ret
    
    print nth_root(124, 3)
    print nth_root(125, 3)
    print nth_root(126, 3)
    print nth_root(1, 100)
    

    Here, both val and n are expected to be integer and positive. This makes the return expression rely exclusively on integer arithmetic, eliminating any possibility of rounding errors.

    Note that accuracy is only guaranteed when val**(1./n) is fairly small. Once the result of that expression deviates from the true answer by more than 1, the method will no longer give the correct answer (it'll give the same approximate answer as your original version).

    Still I am wondering why int(125**(1/3)) is 4

    In [1]: '%.20f' % 125**(1./3)
    Out[1]: '4.99999999999999911182'
    

    int() truncates that to 4.

    0 讨论(0)
  • 2020-12-01 17:00

    I wonder if starting off with a method based on logarithms can help pin down the sources of rounding error. For example:

    import math
    def power_floor(n, k):
        return int(math.exp(1.0 / k * math.log(n)))
    
    def nth_root(val, n):
        ret = int(val**(1./n))
        return ret + 1 if (ret + 1) ** n == val else ret
    
    cases = [
        (124, 3),
        (125, 3),
        (126, 3),
        (1, 100),
        ]
    
    
    for n, k in cases:
        print "{0:d} vs {1:d}".format(nth_root(n, k), power_floor(n, k))
    

    prints out

    4 vs 4
    5 vs 5
    5 vs 5
    1 vs 1
    
    0 讨论(0)
  • 2020-12-01 17:10

    You can round to nearest integer instead of rounding down / to zero (I don't know what Python specifies) :

    def rtn (x):
        return int (x + 0.5)
    
    >>> rtn (125 ** (1/3))
    5
    
    0 讨论(0)
  • 2020-12-01 17:11

    Do this before everything:

    from __future__ import division
    

    and then run any of the above specified techniques to have your results.

    0 讨论(0)
  • 2020-12-01 17:13

    int(125**(1/3)) should clearly be 5, i.e. the right answer, so this must be standard computer rounding error, i.e internally the result is 4.9999999999 which gets rounded down to 4. This problem will exist with whatever algorithm you use. One simple ad-hoc solution is to add a tiny number e.g. int((125**(1/3)) + 0.00000001)

    0 讨论(0)
提交回复
热议问题