Search code examples
pythonlogiccalculator

Write a function that calculates log base 2 of a given number


I'm a newbie at python so sorry in advance is this is a really simple problem.

Question: We are asked to write a custom function that calculates b in log_2(x) = b given x (log base 2 of x).

Note: The variable x is given as float and we are not allowed to use any of python's built-in functions like pow() or import any packages.

Examples:

Given 8, return "3"
Given 9, return "between 3 and 4"
Given 0.4, return "between -1 and -2"

All return types take the format of a string (we are allowed to use str()).

My attempt: Since log_2(x) = b essentially equals to 2^b = x, I tried iterating over the value b and see if the x value is equal to the given number. However, I forgot that the given number is a float, and not an integer.

def log_base_2(number: float) -> str:
    power = 0
    BASE = 2

    if number <= 0:
        raise Exception('Sorry, your input is incorrect!') 

    while True:
        if number == calc_power(BASE, power):
            return str(power)
        elif number > calc_power(BASE, power) and number < calc_power(BASE, power + 1):
            return f"between {power} and {power + 1}"
        else:
            power += 1
 

# helper method for calculating the power
def calc_power(base: float, power: float):
    if power == 0:
        return 1

    multiple = base
    for i in range (1, power):
        base *= multiple 
    return base

This doesn't work essentially because I've only taken integers into consideration and that it can't calculate floats.

I'm not very sure how to write an exponent calculator that would calculate a float type power. I'd appreciate any help and if you an easier way to solve this problem please let me know!


Solution

  • Here's an answer by rewriting your current function:

    def log_base_2(number: float) -> str:
        power = 0
        BASE = 2
        power2 =0
        # create new power variable that counts -ve
    
        if number <= 0:
            raise Exception('Sorry, your input is incorrect!') 
    
        while True:
            if number == calc_power(BASE, power):
                return str(power)
            elif number > calc_power(BASE, power) and number < calc_power(BASE, power + 1):
                return f"between {power} and {power + 1}"
            elif number < calc_power(BASE, power2) and number > calc_power(BASE, power2-1):
                return f"between {power2} and {power2-1}"
            # this elif wants to also check powers in the negative direction
            else:
                power += 1
                power2 -= 1
                # increment -ve power
     
    
    # helper method for calculating the power
    def calc_power(base: float, power: float):
        if power == 0:
            return 1
        multiple = base
        
        if power < 0: # check for -ve powers
                power *= -1 # change power to +ve
                for i in range(power,1,-1): # loop backwards
                    multiple *= 2 # 2^power
                base = (1 / multiple) # to be a -ve power, it must be inverse
        else:
            for i in range (1, power):
                base *= multiple
        return base
    

    There might be a better way that involves less function calls but this is what I can think of right now.