I have to use a lot of logarithmic calculations in one program. In terms of the logarithmic base, the procedure is not specific. I was wondering, if any base n
(2? 10? e?) is faster in the Python 3.5 math
module than others, because maybe under the hood all other bases a
are transformed into log_a(x) = log_n(x)/log_n(a)
. Or does the choice of the base not influence the speed of the calculation, because all bases are implemented in the same way using a C library?

- 11,960
- 10
- 32
- 54
-
1Possible duplicate of [Where can I inspect Python's math functions?](https://stackoverflow.com/questions/5476189/where-can-i-inspect-pythons-math-functions) – internet_user Dec 18 '17 at 16:57
-
Are you using `numpy` or another library? Are you functions using vectors/vectorized methods? – Jon Dec 18 '17 at 17:00
-
You could try to do some benchmarking yourself, but depending on your code it is likely that, even if there is any difference at all, it will be largely eclipsed by other types of overhead. – jdehesa Dec 18 '17 at 17:01
-
@Jon No, the standard Python `math` module. I assume, `np.log` would be faster, but I don't really want to use `numpy` in this case. – Mr. T Dec 18 '17 at 17:03
-
@jdehesa Thought about it, but if the implemented `n` is for whatever reason e, 1024 or any other number that has an advantage for the calculation in a specific processor architecture, what are my chances to detect this? This and my inexperience as a Python beginner to design a good benchmark test that gets rid of the mentioned overhead. – Mr. T Dec 18 '17 at 17:07
-
1On x86 the instruction for calculating log has a multiplier built in, so the base doesn't matter at all - at least for compiled code. Since Python is interpreted I'm not sure if that applies. – Mark Ransom Dec 18 '17 at 17:14
-
2In this specific case it looks like `math.log` uses C's standard library `log` function, so speed will depend on the platform. – internet_user Dec 18 '17 at 17:17
-
@pycoder Platform dependent, but base independent? Platform meaning the interpreter, I guess? Well, if that's the case, write it as an answer and I will accept it. – Mr. T Dec 18 '17 at 17:20
-
Well, `log` is `ln` here, and `math.log` always does `ln(n)/ln(base)`, so base independent. Platform in this case is your C standard library implementation. – internet_user Dec 18 '17 at 17:27
2 Answers
In CPython, math.log
is base independent, but platform dependent. From the C source for the math
module, on lines 1940-1961, the code for math.log
is shown.
math_log_impl(PyObject *module, PyObject *x, int group_right_1,
PyObject *base)
/*[clinic end generated code: output=7b5a39e526b73fc9 input=0f62d5726cbfebbd]*/
{
PyObject *num, *den;
PyObject *ans;
num = loghelper(x, m_log, "log"); // uses stdlib log
if (num == NULL || base == NULL)
return num;
den = loghelper(base, m_log, "log"); // uses stdlib log
if (den == NULL) {
Py_DECREF(num);
return NULL;
}
ans = PyNumber_TrueDivide(num, den);
Py_DECREF(num);
Py_DECREF(den);
return ans;
}
This, no matter what, calculates the natural log of the number and base, so unless the C log
function has a special check for e
, it will run at the same speed.
This source also explains the other answer's log2
and log10
being faster than log
. They are implemented using the standard library log2
and log10
functions respectively, which will be faster. These functions, however, are defined differently depending on the platform.
Note: I am not very familiar with C so I may be wrong here.

- 3,149
- 1
- 20
- 29
-
1I am not in the position to interpret the C code. But I understand from this that `log(x), log2(x), log10(x)` should have the same speed, because they use the same C library strategies. And `log(x, n)` is slower, because it uses the logarithmic formula from my question. – Mr. T Dec 18 '17 at 18:43
Interesting question. I did some "good old" field test (CPython 3.6.2 on Linux, x86_64, i7-3740QM CPU - Python interpreter compiled with all optimizations available for this CPU turned ON).
>>> math.log10(3)
0.47712125471966244
>>> math.log(3, 10)
0.47712125471966244
>>> timeit.timeit('math.log(3, 10)', setup = 'import math')
0.2496643289923668
>>> timeit.timeit('math.log10(3)', setup = 'import math')
0.14756392200069968
Log10 is clearly faster than log(n, 10).
>>> math.log2(3.0)
1.584962500721156
>>> math.log(3.0, 2.0)
1.5849625007211563
>>> timeit.timeit('math.log2(3.0)', setup = 'import math')
0.16744944200036116
>>> timeit.timeit('math.log(3.0, 2.0)', setup = 'import math')
0.22228705599263776
Log2 is also clearly faster than log(n, 2). Btw, either way, floats and ints are equally fast.
With numpy
, the picture is different. It kind of does not matter what you do:
>>> timeit.timeit('numpy.log(numpy.arange(1, 10))', setup = 'import numpy')
2.725074506000965
>>> timeit.timeit('numpy.log10(numpy.arange(1, 10))', setup = 'import numpy')
2.613872367001022
>>> timeit.timeit('numpy.log2(numpy.arange(1, 10))', setup = 'import numpy')
2.58251854799164

- 3,433
- 2
- 34
- 71