Logarithms are easier to calculate if you can write your input as a power of the base. In this case, .
In general, . So writing the input as a power of your base gives you the easiest way to evaluate a logarithm. If the input and base aren't related by a nice power relationship, you may have to relate them to known values or use a calculator.
Logarithms are easier to calculate if you can write your input as a power of the base. In this case, .
In general, . So writing the input as a power of your base gives you the easiest way to evaluate a logarithm. If the input and base aren't related by a nice power relationship, you may have to relate them to known values or use a calculator.
Regarding if
you can just multiply
by
. The amount of times you can do so without going over
is the
.
Same with except you divide by
instead without going below
.
.net - How can I compute a base 2 logarithm without using the built-in math functions in C#? - Stack Overflow
How do computers computer log base 2 computations?
log base 2 of 3 without calculator (Check)
How are logarithms calculated without calculators?
Videos
Assuming you're only interested in the integral part of the logarithm, you can do something like that:
static int LogBase2(uint value)
{
int log = 31;
while (log >= 0)
{
uint mask = (1 << log);
if ((mask & value) != 0)
return (uint)log;
log--;
}
return -1;
}
(note that the return value for 0 is wrong; it should be negative infinity, but there is no such value for integral datatypes so I return -1 instead)
http://graphics.stanford.edu/~seander/bithacks.html
In math, using the natural log makes problems just work (this isn't a math post, so I'm not going to elaborate). I want to use log properties to try to improve some math operations in a program I've written and optimize my code a little bit. I'm inevitably going to have to do log base 2 of a float, and I was wondering how a computer would implement a log base 2 function. Additionally, how does log base 2 operation performance compare to division or square roots, and finally, are there any approximations I should know about for log base 2 as there is for the sine function (at certain x values)?
I got this question from this video and there were 4 options:
https://www.youtube.com/watch?v=X6C5hGpWW5A
can anyone tell me if my method was accurate, (the guy in the video used a more simpler method but here's mine):
we know 2>x>1 (2^2 = 4 >3 > 2^1 =2) then I took three values as x from the question:
(i) 2^ 3/2 = 2 *sq rt (2)
(ii) 2 ^ 4/3 = 2* cub rt (2)
(iii) 2 ^ 5/3 = 2* cub rt (4)
As (ii) n (iii) are the closest values to 3, log base 2 of 3 must lie between 1 1/2 and 1 2/3. How accurate do you think this method would be? I will really really enjoy some feedback it has really been bugging me.
I don't mean the basic/easy ones like log100 base 10, log 4 base 2 etc., rather log(0.073) base 10? For pH-calculations for example. People must have had a way of solving it to know acidities before calculators were invented. I tried googling it, all I got was some 9th grade stuff on what a logarithm is
To evaluate $\log_8 128$, let $$\log_8 128 = x$$ Then by definition of the logarithm, $$8^x = 128$$ Since $8 = 2^3$ and $128 = 2^7$, we obtain \begin{align*} (2^3)^x & = 2^7\\ 2^{3x} & = 2^7 \end{align*} If two exponentials with the same base are equal, then their exponents must be equal. Hence, \begin{align*} 3x & = 7\\ x & = \frac{7}{3} \end{align*}
Check: If $x = \frac{7}{3}$, then $$8^x = 8^{\frac{7}{3}} = (8^{\frac{1}{3}})^7 = 2^7 = 128$$
Using $\log_xy=\dfrac{\log_ay}{\log_ax}$ and $\log(z^m)=m\log z$ where all the logarithms must remain defined unlike $\log_a1\ne\log_a(-1)^2$
$$\log_8{128}=\dfrac{\log_a(2^7)}{\log_a(2^3)}=\dfrac{7\log_a2}{3\log_a2}=?$$
Clearly, $\log_a2$ is non-zero finite for finite real $a>0,\ne1$
See Laws of Logarithms
I have tried to run most of the methods from different answers from 1 and 2 where I found that power_of_2 and easy show a good performance.
import math
import timeit
def myLog(x, b):
if x < b:
return 0
return 1 + float(myLog(x / b, b))
def easy(x):
return x.bit_length() - 1
def brute(x):
# determine max p such that 2^p <= x
p = 0
while 2 ** p <= x:
p += 1
return p - 1
def log2_approx(val):
from math import floor
val = floor(val)
approx = 0
while val != 0:
val &= ~ (1 << approx)
approx += 1
return approx
def log2(n):
i = 0
while n > 1:
n >>= 1
i += 1
return i
def power_of_2(n):
return (n & (n - 1) == 0) and n != 0
def log2_fast(n):
return math.frexp(33554436)[1] - 1
import time
from functools import partial
import time
start_time = time.time()
math.log2(33554432)
print("math.log2 is %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
myLog(33554432.0, 2.0)
print(" myLog is %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
brute(33554432)
print(" brute is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
log2_approx(33554432) - 1
print("log2_approx is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
log2_fast = math.frexp(33554436)[1] - 1
print(" log2_fast is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
log2(33554432)
print("log2 is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
power_of_2(33554432)
print("power_of_2 is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
start_time = time.time()
easy(33554432)
print("easy is --- %s microseconds ---" % ((time.time() - start_time) * 1000000))
Running time
math.log2 is 3.0994415283203125 microseconds ---
myLog is 5.4836273193359375 microseconds ---
brute is --- 6.4373016357421875 microseconds ---
log2_approx is --- 6.4373016357421875 microseconds ---
log2_fast is --- 1.6689300537109375 microseconds ---
log2 is --- 2.1457672119140625 microseconds ---
power_of_2 is --- 0.7152557373046875 microseconds ---
easy is --- 0.476837158203125 microseconds ---
Using timeit shows delay
test_items=33554432
base=2
times = timeit.Timer(partial(math.log2, test_items))
print("math.log2 is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(myLog, test_items,base))
print("myLog is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(easy, test_items))
print("easy is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(brute, test_items))
print("brute is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(log2_approx, test_items))
print("log2_approx is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(log2, test_items))
print("log2 is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(power_of_2, test_items))
print("power_of_2 is %s microseconds ---", (times.timeit(1000000)))
times = timeit.Timer(partial(log2_fast, test_items))
print("log2_fast is %s microseconds ---", (times.timeit(1000000)))
Running time
math.log2 is %s microseconds --- 0.05126429593656212
myLog is %s microseconds --- 4.137887543998659
easy is %s microseconds --- 0.10356121498625726
brute is %s microseconds --- 5.254867412033491
log2_approx is %s microseconds --- 3.81522585300263
log2 is %s microseconds --- 1.7966924259671941
power_of_2 is %s microseconds --- 0.1572157460032031
log2_fast is %s microseconds --- 0.21886748599354178
If your code needs to call this function repeatedly, and the inputs are guaranteed to be even integer powers of two (unlike your example!) I imagine it's going to be hard to beat a hard-coded dictionary lookup.
def precalculate_pow2(ceiling):
i = 1
result = dict()
for n in range(ceiling):
result[i] = n
i <<= 1
return result
powersof2 = precalculate_pow2(500) # or whatever your upper limit is
def log2(n):
return powersof2[n]
Obviously, the loop to calculate the values is no more efficient than your current code, but memoizing it allows you to amortize that cost over all the calls to the log2 function.
As a variation, you could start with the dictionary containing only one value, and only populate the missing parts on subsequent calls, using a recursive function.
powersof2 = {1: 0}
def log2(n):
if n not in powersof2:
powersof2[n] = 1 + log2(n >> 1)
return powersof2[n]
This has the obvious drawback that it will go into an endless loop if you call it with a negative value (though Python will then throw a traceback once you exhaust the maximum recursion limit).