is_perfect is a method to check whether a number has a perfect nth root.
For example:
- is_perfect(125,3) should return True as 5^3 is 125 an integer
- is_perfect(126,3) should return False as there is no integer M for which M^3 is an integer
def is_perfect(num,power):
root = 0.00
p = 0.00
float(p)
p = 1.0/power
root = num**(p)
print ("root",root,sep = ' ')
print ("root**power",root**power,sep = ' ')
check = num -(root**power)
print (check)
if check < 1e-14:
root = math.ceil(root)
if (root-int(root)) ==0:
print(num,root,int(root),p,sep = ' ')
return True
else:
print(num,root,int(root),p,sep=' ')
return False
In Python shell both give False when the result of 125 should be true.
>>> is_perfect(126,3)
root 5.0132979349645845
root**power 125.99999999999999
1.4210854715202004e-14
126 5.0132979349645845 5 0.3333333333333333
False
>>> is_perfect(125,3)
root 4.999999999999999
root**power 124.99999999999993
7.105427357601002e-14
125 4.999999999999999 4 0.3333333333333333
False
>>>
How can I modify my method to achieve the desired result.
To avoid rounding errors in floating-point comparisons, you'll have to do some rounding and perform a final confirmation using integers:
def is_perfect( value, exponent ):
root = value ** ( 1.0 / exponent )
root = long( round( root ) )
return root ** exponent == value
To test:
[ x for x in range( 1000 ) if is_perfect( x, 3 ) ]
Output:
[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]
Let's write a diagnostic test to see how high it can go:
def test( root, exponent ): # should print [False, True, False]
print( [ is_perfect( root ** exponent + i, exponent ) for i in ( -1, 0, +1 ) ] )
For me, with an exponent of 19, the test
fails when the root
reaches somewhere in the 14 digit range. At this point when value = root**exponent
is computed, value
is around 900 bits long.
test( 100000000000000, 19) # prints [False, True, False]
test( 999999999999999, 19) # prints [False, False, False]