Based on this answer, I'm implementing a simple algorithm in Python 3.x to determine whether or not a integer n
is a power of another integer base
. However, the algorithm doesn't return the correct result. The code in the linked answer is:
while (n % 3 == 0) {
n /= 3;
}
return n == 1;
(A comment indicates that checking n == 0
is also necessary, logically). This is my code:
def is_power(n: int, base: int) -> bool:
if n == 0:
return false
while (n % base == 0):
n /= base
return n == 1
I wrote simple testing code that tests a certain range of bases and exponents, but the results it returns are incorrect. Testing code:
for base in range(3, 10):
print("Base: {0}".format(base))
for exp in range(30, 40):
b = is_power(pow(base, exp), base)
if not(b):
print("{: <3}: {: <5}".format(exp, str(b)))
I tested this with a much larger range, but for the sake of output, I limited it in this example. This outputs:
Base: 3
35 : False
36 : False
37 : False
38 : False
39 : False
Base: 4
Base: 5
30 : False
31 : False
32 : False
33 : False
34 : False
35 : False
36 : False
37 : False
38 : False
39 : False
Base: 6
35 : False
36 : False
37 : False
38 : False
39 : False
Base: 7
30 : False
31 : False
32 : False
33 : False
34 : False
35 : False
36 : False
37 : False
38 : False
39 : False
Base: 8
Base: 9
30 : False
31 : False
32 : False
33 : False
34 : False
35 : False
36 : False
37 : False
38 : False
39 : False
which is clearly incorrect. I've tried debugging a small example, where n = pow(3, 35)
and base = 3
yields these values of n
in the loop:
50031545098999707
1.6677181699666568e+16
and the loop ends, because 50031545098999707 / 3 == 1.667718169966656 9 e+16 (note that the last digit is different). Is this the problem? Are Python's calculations failing? If not, what is the problem with this algorithm?
The algorithm also fails even more if I use math.pow
instead, but I'm not necessarily surprised by that, since checking one example demonstrates that pow
and math.pow
don't always return the same value.
import math
pow(3, 35) == math.pow(3, 35) # 50031545098999707 != 5.0031545098999704e+16