Home > OS >  How can I write this code so that I do not have to round the logarithm?
How can I write this code so that I do not have to round the logarithm?

Time:08-25

I was doing a programming challenge question where you need to found out if a given number (n) is equal to 3 raised to some exponent(x)

9 is True since 3^x -> 3^3 = 9

10 is False since no x for 3^x is equal to 10

my problem occurred when 243 was entered into my code, which returned a result of 4.999 repeating.

my solution was to simply add a round function, in which I arbitrarily decided on 5 decimal places, this solved the problem.

now another problem occurred when the input was 531440, this returns an x value of 11.999998287222695 which, according to the challenge, was false, but with my code returned a true since I rounded to the fifth decimal place. I then changed my round to 10 decimal places and this fixed the code.

I was wondering if there was a way to implement my solution without having to round, as I'm sure if I plugged in enough numbers eventually another one would need to round past >10 decimal places and cause my code to fail. Please see the code below.

import math as math

def isPowerOfThree(n):
    print(math.log(n,3))                                     #this line prints the unrounded log result
    print(round((math.log(n,3)),10))                         #this line prints the rounded result
    return n>0 and round((math.log(n,3)),10).is_integer()

n = 243
print(isPowerOfThree(n))

CodePudding user response:

The 'trick' allowing to avoid problems with chosen precision is to round to an integer and then check if this exponent gives the required result. The code below implements this approach:

import math

def isPowerOfThree(N):
    if 3**round(math.log(N,3)) == N:
        return True
    return False

N = 531440 # 243
print(isPowerOfThree(N)) # gives False

Another approach will be to check all powers of 3 against the target number:

def isPowerOfThree(N):
    x = 1
    while True:
        n = 3**x
        if n == N:
            return True
        elif n > N:
            return False
        x  = 1

And here an approach detecting directly without the need to run multiple loop runs if a number is not a power of 3:

def isPowerOfThree(N):
    while True: 
        N , r = divmod(N, 3)
        if r != 0: 
            return False
        if N == 1:
            return True

P.S. the two last approaches provide code to what Karl Knechtel mentioned in his comment to the question.

  • Related