Get logarithm without math log python

Question:

I need to generate the result of the log.

I know that:

enter image description here

Then I made my code:

def log(x, base):
    log_b = 2
    while x != int(round(base ** log_b)):
        log_b += 0.01
        print(log_b)
    return int(round(log_b))

But it works very slowly. Can I use other method?

Asked By: dragon_ball

||

Answers:

You can use binary search for that.
You can get more information on binary search on Wikipedia:

# search for log_base(x) in range [mn, mx] using binary search
def log_in_range(x, base, mn, mx):
    if (mn <= mx):
        med = (mn + mx) / 2.0
        y = base ** med
        if abs(y - x) < 0.00001:   # or if math.isclose(x, y): https://docs.python.org/3/library/math.html#math.isclose
            return med
        elif x > y:
            return log_in_range(x, base, med, mx)
        elif x < y:
            return log_in_range(x, base, mn, med)
    return 0

# determine range using doubling search, then call log_in_range
def log(x, base):
    if base <= 0 or base == 1 or x <= 0:
        raise ValueError('math domain error')
    elif 0 < base < 1:
        return -log(x, 1/base)
    elif 1 <= x and 1 < base:
        mx = 1
        y = base
        while y < x:
            y *= y
            mx *= 2
        return log_in_range(x, base, 0, mx)
    elif 0 <= x < 1 and 1 < base:
        mn = -1
        y = 1/base
        while y > x:
            y = y ** 0.5
            mn *= 2
        return log_in_range(x, base, mn, 0)
Answered By: Mihail Burduja

Comparison:-

This is how your log works:-

def your_log(x, base):
    log_b = 2
    while x != int(round(base ** log_b)):
        log_b += 0.01
        #print log_b
    return int(round(log_b))

print your_log(16, 2)

# %timeit %run your_log.py
# 1000 loops, best of 3: 579 us per loop

This is my proposed improvement:-

def my_log(x, base):
    count = -1

    while x > 0:
        x /= base
        count += 1
        if x == 0:
            return count


print my_log(16, 2)

# %timeit %run my_log.py
# 1000 loops, best of 3: 321 us per loop

which is faster, using the %timeit magic function in iPython to time the execution for comparison.

Answered By: Calvin Cheng

One other thing you might want to consider is using the Taylor series of the natural logarithm:

enter image description here
enter image description here

Once you’ve approximated the natural log using a number of terms from this series, it is easy to change base:

enter image description here


EDIT: Here’s another useful identity:

enter image description here

Using this, we could write something along the lines of

def ln(x):
    n = 1000.0
    return n * ((x ** (1/n)) - 1)

Testing it out, we have:

print ln(math.e), math.log(math.e)
print ln(0.5), math.log(0.5)
print ln(100.0), math.log(100.0)

Output:

1.00050016671 1.0
-0.692907009547 -0.69314718056
4.6157902784 4.60517018599

This shows our value compared to the math.log value (separated by a space) and, as you can see, we’re pretty accurate. You’ll probably start to lose some accuracy as you get very large (e.g. ln(10000) will be about 0.4 greater than it should), but you can always increase n if you need to.

Answered By: arshajii

I used recursion:

def myLog(x, b):
    if x < b:
        return 0  
    return 1 + myLog(x/b, b)
Answered By: leizeQ

It will be long process since it goes in a loop. Therefore,

def log(x,base):
    result = ln(x)/ln(base)
    return result

def ln(x):
    val = x
    return 99999999*(x**(1/99999999)-1)

log(8,3)

Values are nearly equal but not exact.

Answered By: Prakash Dahal
import math
try :
    number_and_base = input() ##input the values for number and base

    ##assigning those values for the variables
    number = int(number_and_base.split()[0])
    base = int(number_and_base.split()[1])
##exception handling
except ValueError :
    print ("Invalid input...!")

##program

else:
    n1 = 1 ##taking an initial value to iterate
    while(number >= int(round(base**(n1),0))) : ##finding the most similer value to the number given, varying the vlaue of the power
        n1 += 0.000001 ##increasing the initial value bit by bit

    n2 = n1-0.0001
    if abs(number-base**(n2)) < abs(base**(n1)-number) :
        n = n2
    else :
        n = n1

    print(math.floor(n)) ##output value
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.