Is cube root integer?
If your numbers aren't big, I would do:
def is_perfect_cube(number):
return number in [x**3 for x in range(15)]
Of course, 15
could be replaced with something more appropriate.
If you do need to deal with big numbers, I would use the sympy
library to get more accurate results.
from sympy import S, Rational
def is_perfect_cube(number):
# change the number into a sympy object
num = S(number)
return (num**Rational(1,3)).is_Integer
For small numbers (<~1013 or so), you can use the following approach:
def is_perfect_cube(n):
c = int(n**(1/3.))
return (c**3 == n) or ((c+1)**3 == n)
This truncates the floating-point cuberoot, then tests the two nearest integers.
For larger numbers, one way to do it is to do a binary search for the true cube root using integers only to preserve precision:
def find_cube_root(n):
lo = 0
hi = 1 << ((n.bit_length() + 2) // 3)
while lo < hi:
mid = (lo+hi)//2
if mid**3 < n:
lo = mid+1
else:
hi = mid
return lo
def is_perfect_cube(n):
return find_cube_root(n)**3 == n
In SymPy there is also the integer_nthroot
function which will quickly find the integer nth root of a number and tell you whether it was exact, too:
>>> integer_nthroot(primorial(12)+1,3)
(19505, False)
So your function could be
def is_perfect_cube(x): return integer_nthroot(x, 3)[1]
(And because SymPy is open source, you can look at the routine to see how integer_nthroot
works.)
To elaborate on the answer by @nneonneo, one could write a more general kth-root function to use instead of cube_root,
def kth_root(n,k):
lb,ub = 0,n #lower bound, upper bound
while lb < ub:
guess = (lb+ub)//2
if pow(guess,k) < n: lb = guess+1
else: ub = guess
return lb
def is_perfect_cube(n):
return kth_root(n,3) == n