Search code examples
pythonpython-3.xmathlogarithm

How do I ensure that a number is a power of another number using logarithmic property in Python3?


I want to check if a number x is an exponential power of another number, y. I understand mathematics: use logarithms.

However, when I did this approach in Python3, using log() function, I got weird results. I wanted to test whether 243 is a power of 3, which it is, my code returned False. My code is as follows:

power = log(n, 3)
if (int(power)) == power:
    return True

I get 4.999999999999999 as the result in power. I read about the precision and other tactical details pertaining to floating points and logarithms in Python3 and I tried those solutions but none of them gave me the answer that I know is correct as far as basic maths is concerned.

I tried this:

from math import log
from decimal import Decimal, Context

class Power:
    def power_func(self, n: int) -> bool:
        if n == 0:
            return False
        ctx = Context(prec=20)
        power = log(n, Decimal(3))
        if (int(power)) == power:
            return True
        return False

I think I am missing some basics of Python here but not sure how to proceed further. I know other solutions to do the task but I wanted to achieve this using logarithms in Python3.


Solution

  • Don't use logarithms; they rely on real arithmetic to work correctly, which Python cannot do.

    Instead, use repeated squaring to approach n from the base.

    def is_power_of(n, b):
        y = b
        # Compute y = b**2, b**4, ..., b**2**i until y reaches or exceeds n
        # i = 1
        while y < n:
            y = y * y
            # i *= 2
    
        # If we overshoot, divide by b until we either
        # reach n or get a non-zero remainder
        while y > n:
            y, r = divmod(y, b)
            # i -= 1
            if r:
                return False
        else:
            return y == n
    

    Note that if the function returns true, i will be the value such that b**i == n.