Question

This seems to be simple but I cannot find a way to do it. I need to show whether the cube root of an integer is integer or not. I used is_integer() float method in Python 3.4 but that wasn't successful. As

x = (3**3)**(1/3.0) 
is_integer(x)    
True

but

x = (4**3)**(1/3.0) 
is_integer(x)    
False

I tried x%1 == 0,x == int(x) and isinstance(x,int) with no success.

I'd appreciate any comment.

Was it helpful?

Solution

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

OTHER TIPS

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

This is another approach using the math module.

import math
num = int(input('Enter a number: '))
root = int(input('Enter a root: '))
nth_root = math.pow(num, (1/root))
nth_root = round(nth_root, 10)
print('\nThe {} root of {} is {}.'.format(root, num, nth_root))
decimal, whole = math.modf(nth_root)
print('The decimal portion of this cube root is {}.'.format(decimal))
decimal == 0

Line 1: Import math module.
Line 2: Enter the number you would like to get the root of.
Line 3: Enter the nth root you are looking for.
Line 4: Use the power function.
Line 5: Rounded to 10 significant figures to account for floating point approximations.
Line 6: Print a preview of the nth root of the selected number.
Line 7: Use the modf function to get the fractional and integer parts.
Line 8: Print a preview of decimal part of the cube root value.
Line 9: Return True if the cube root is an integer. Return False if the cube root value contains fractional numbers.

in Python 3.11 you can use math.cbrt

 x = 64
 math.cbrt(x).is_integer

(or)

or use numpy.cbrt

import numpy as np
x = 64
np.cbrt(x).is_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

I think you should use the round function to get the answer. If I had to write a function then it will be as follows:

def cube_integer(n):
    if round(n**(1.0/3.0))**3 == n:
        return True
    return False

You can use something similar to int(n**(1.0/3.0)) == n**(1.0/3.0), but in python because of some issues with the computation of the value of cube root, it is not exactly computed. For example int(41063625**(1.0/3.0)) will give you 344, but the value should be 345.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top