math.log uses floats and these almost always involve some rounding errors.
>>> math.log(1000, 10)
2.9999999999999996
If you need it to be exact you should change your algorithm to generate the powers of 10 (simply multiply the last power by 10) and continue as long as the new power is smaller than your input number.
>>> limit = 12345
>>> power = 10
>>> while power < limit:
... print power
... power = power * 10
...
10
100
1000
10000
This is guaranteed to be exact as it does not involve any floating point numbers. (And is a lot faster, too)
Answer from bikeshedder on Stack Overflowmath.log in Python - Stack Overflow
Math.log() method complexity
Error in math.log() method
Source code for logarithmic function
Videos
math.log uses floats and these almost always involve some rounding errors.
>>> math.log(1000, 10)
2.9999999999999996
If you need it to be exact you should change your algorithm to generate the powers of 10 (simply multiply the last power by 10) and continue as long as the new power is smaller than your input number.
>>> limit = 12345
>>> power = 10
>>> while power < limit:
... print power
... power = power * 10
...
10
100
1000
10000
This is guaranteed to be exact as it does not involve any floating point numbers. (And is a lot faster, too)
Floating-point math strikes again! Look at the values returned by math.log:
>>> math.log(10000, 10)
4.0
>>> math.log(1000, 10)
2.9999999999999996
>>> math.log(100, 10)
2.0
>>> math.log(10, 10)
1.0
I add math.log() method in a function but it took more step to compute than iterative version of the same function unless input is power of 2 because log is base 2. What I want to learn is does math.log() method have more than constant time complexity ?
Hi everyone, I was wondering if anyone know the source code for calculating logarithmic function in Python Math module. I tried googling for a while but no success. Just curious how people write code for math.
Thank you so much!!
Apparently everyone knew about this trick except for me.
I often find myself wanting to get the log2 of a number. I figured there was an obvious answer but I could never figure out how to do it, given that most math libraries only offer two log functions: log (typically base e) and log10 (base 10). Sometimes you luck out and get a log that offers an "arbitrary base" parameter, but most of the time not.
So how do you calculate the log2() of a number, if you only have loge() or log10()? Incredibly easy.
num = log10(1024.0) // what number you'd like to process den = log10(2.0) // base goes here result = num / den >>> from math import log10 >>> log10(1024.0)/log10(2.0) # log2(2**10) 10.0 >>> log10(65536)/log10(16) # log16(2**16) 4.0 # and for sanity: >>> from math import log, log10, e >>> log(65536) 11.090354888959125 >>> log10(65536)/log10(e) 11.090354888959125
math.log is the natural logarithm:
From the documentation:
math.log(x[, base]) With one argument, return the natural logarithm of x (to base e).
Your equation is therefore:
n = math.log((1 + (FV * r) / p) / math.log(1 + r)))
Note that in your code you convert n to a str twice which is unnecessary
Here is the correct implementation using numpy (np.log() is the natural logarithm)
import numpy as np
p = 100
r = 0.06 / 12
FV = 4000
n = np.log(1 + FV * r/ p) / np.log(1 + r)
print ("Number of periods = " + str(n))
Output:
Number of periods = 36.55539635919235
One other thing you might want to consider is using the Taylor series of the natural logarithm:

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

EDIT: Here's another useful identity:

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.
I used recursion:
def myLog(x, b):
if x < b:
return 0
return 1 + myLog(x/b, b)