7

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?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
dragon_ball
  • 153
  • 1
  • 1
  • 6
  • 2
    Sure, there are numerous algorithms. How about you do some research on some of those, and come asking a specific question if you need help understanding one? –  Nov 03 '12 at 16:35
  • 8
    this is getting ridiculous... – georg Nov 03 '12 at 16:35
  • 1
    I suspect this is for college assignment. Some professors refuse to let their students use the standard libs. – Sean W. Nov 03 '12 at 16:38
  • To be honest, you don't learn things like this unless you implement things (badly) for yourself the first time – Jakob Bowyer Nov 03 '12 at 16:45
  • 2
    why don't you go thru http://en.wikipedia.org/wiki/Natural_logarithm , it list many methods for calculating log and try to implement them all, and then ask specific question if it didn't work – Anurag Uniyal Nov 03 '12 at 16:59
  • I could swear I saw an identical question today, but I can't find it... ah, here we go: http://stackoverflow.com/questions/13207854/implementing-a-function-that-computes-logarithms okay, that one had broken code though. – phant0m Nov 03 '12 at 17:06

6 Answers6

21

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.

arshajii
  • 127,459
  • 24
  • 238
  • 287
8

I used recursion:

def myLog(x, b):
    if x < b:
        return 0  
    return 1 + myLog(x/b, b)
Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
leizeQ
  • 795
  • 1
  • 7
  • 18
3

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)
Stef
  • 13,242
  • 2
  • 17
  • 28
Mihail Burduja
  • 3,196
  • 2
  • 22
  • 28
  • 2
    Binary search is a search algorithm on a sorted sequence. While the same idea can be applied to other problems, that's a different algorithm (bisection perhaps?). –  Nov 03 '12 at 16:39
  • I suppose [0, x] is a sorted sequence and I search the result using binary search. The complexity is O(logx) – Mihail Burduja Nov 03 '12 at 16:46
  • No, the reals are not discrete, whereas the indices into an sequence are. Of course, you could restrict this to a particular range (and in a sense you're necessarily doing this, by using a finite-precision number representation). But conceptually, it's a different algorithm. –  Nov 03 '12 at 16:48
  • In the same way, using "binary search" you can compute the square root of the value, which is real also. You just need to restrict the number of steps of the algorithms, which you can easily determine, or add an error margin. – Mihail Burduja Nov 03 '12 at 16:52
  • Again, IMHO it's not the binary search algorithm (at least not in the CS sense, I just read bisection is also called "binary search method") even though it builds on a similar concept. It does not search a sequence of values, it approximates a function. That one can explicitly store the values and then search them doesn't make it identical, in the same way binary search isn't a balanced binary search tree. –  Nov 03 '12 at 17:16
  • Hello. I took the liberty of making three edits to this answer. Feel free to rollback one, two or all of these edits if you don't like them. First edit: I fixed an apparent typo in the code. Second edit: I removed the calls to `int(round(...))` since the logarithm of x is not expected to be an integer. Third edit: I added doubling search before the binary search, so that the user can call `log(x, base)` without having to specify `mn` and `mx`. – Stef Jan 16 '23 at 12:13
  • Hello. I took the liberty of making 4 successive edits to this answer. Feel free to rollback one, two three or all of these edits if you don't like them. First edit: I fixed an apparent typo in the code. Second edit: I removed the calls to `int(round(...))` since the logarithm of x is not expected to be an integer. Third edit: I added doubling search before the binary search, so that the user can call `log(x, base)` without having to specify `mn` and `mx`. Fourth edit: I added support for base < 1, for x < 1, and raised an exception for invalid base and for x <= 0. – Stef Jan 16 '23 at 12:27
1
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
Rory Daulton
  • 21,934
  • 6
  • 42
  • 50
  • 3
    Welcome to StackOverflow. Code-only answers are frowned upon. Could you add some explanation to this code, especially about how this code does something that the other answers don't do? Also, if you plan to continue giving answers here, you should learn how to format your answer. I highlighted your code then pressed `Ctrl+K` which indented everything four spaces so it looks like code in the browser. – Rory Daulton Apr 09 '19 at 19:11
  • 1
    Thank you for your advice. I'll observe what you have said here. – Charunie Hansika A.M Apr 18 '19 at 04:38
0

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.

Calvin Cheng
  • 35,640
  • 39
  • 116
  • 167
0

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.

Vaibhav Vishal
  • 6,576
  • 7
  • 27
  • 48
Prakash Dahal
  • 430
  • 3
  • 6