6

I have been reading Algorithms, 4th Edition, and it defines a question as follows:

Write a static method lg() that takes an int value N as an argument and returns the largest int not larger than the base-2 logarithm of N in Java. Do not use Math.

I discovered the following solution:

public static int lg(int N) {
    int x = 0;
    for (int n = N; n > 1; n/= 2) x++;
    return x;
}

I am wondering why that solution works. Why does dividing by 2 continuously allow us to find the largest integer less than the base 2 logarithm of the argument? I do understand Java, just not how this particular algorithm works.

Thank you.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • I'm voting to close this question as off-topic because it is a question about maths, not about programming. – Joe C Dec 29 '18 at 18:27
  • @JoeC You believe I should ask it at the Mathematics Stack Exchange? –  Dec 29 '18 at 18:28
  • I am not enough of an expert on that site to be able to advise on that, other than pointing you to their [help center](https://math.stackexchange.com/help) so that you can make that judgment. – Joe C Dec 29 '18 at 18:31
  • @JoeC https://meta.stackexchange.com/questions/165519/where-should-i-post-questions-about-algorithms-stack-overflow-or-software-engin – Naman Dec 29 '18 at 18:41
  • logarithm of x with base 2 amounts to how many times x can be divided by 2 up to reaching 1, inclusively – Soner from The Ottoman Empire Dec 29 '18 at 19:07

4 Answers4

3

This has to do with properties of exponents and logarithms. The main observation you need is that

2lg n = n,

because logarithms are the inverses of exponentials. Rearranging that expression gives

1 = n / 2lg n.

In other words, the value of lg n is the number of times you have to divide n by two in order to drop it to 1. This, by the way, is a really great intuition to have when studying algorithms, since log terms show up all the time in contexts like these.

There are some other nuances here about how integer division works, but this is the basic idea behind why that code works.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Thanks. By lg, do you mean the natural logarithm or the base 10 log? –  Dec 29 '18 at 18:32
  • 1
    The convention I’ve seen in CS is that lg refers to the base-two logarithm. You can check this by noting that only the base-2 logarithm meets the above mathematical requirements. – templatetypedef Dec 29 '18 at 18:37
  • @templatetypedef "ISO 31-11 and ISO 80000-2 standards recommend, `lb n`. According to these standards, `lg n` should not be used for the binary logarithm, as it is instead reserved for the common logarithm `log10 n`." In short when in doubt specify base. – Kashyap Jan 01 '19 at 23:51
  • I didn’t know that! I’ve seen the lg convention used in a lot of papers, usually in contexts where it couldn’t be confused with other log bases. – templatetypedef Jan 02 '19 at 00:00
1

Its follows trivially from the logarithmic identity log(a/b) = log(a) - log(b).

You are searching for the largest integer x so that:

x <= log2(n)

Using the identity above and taking in account that log2(2) = 1 we get:

x <= log2(n/2) + log2(2)
x <= log2(n/2) + 1
x <= log2(n/4) + 2
x <= log2(n/8) + 3
...
x <= log2(1) + k            
x <= k                   (since log2(1) = 0)

So x is the number of times you divided n by 2 before reaching 1.

Georgi Gerganov
  • 1,006
  • 9
  • 17
0

The answer is purely Mathmatics,

log₂(n) = ln(n)/ln(2) = x

By applying the rules of exponential:

ln(n) = ln(2)*(x)

n = 2^x

Therefore you have to divide by 2 until the value is smaller than 1 in order to get the closest int to it.

Community
  • 1
  • 1
Mohammad Kurjieh
  • 1,043
  • 7
  • 16
0

We are looking for the largest integer x such that x <= log_2(N) i.e. 2^x <= N

or equivalent 2^x <= N < 2^{x+1}

Let N_0=N

and for k > 0, N_k the quotient of the division of N_{k-1} by 2 and r_k in {0, 1} the remainder (N_{k-1} = 2.N_k + r_k)

We have:

2^{x-1} <= N_1 + (r_1 / 2) < 2^x

But 0 <= r_1 / 2 <= 1/2 and the others numbers are integers so that is equivalent to

2^{x-1} <= N_1 < 2^x

We have successively:

2^{x-1} <= N_1 < 2^x

2^{x-2} <= N_2 < 2^{x-1}

2^{x-x} <= N_x < 2^{x-x+1}

The last is also written 1 <= N_x < 2

But N_x is an integer so N_x = 1

Hence x is the number of division by 2 of N remaining greater or equal than 1.

Instead of starting from N_1, we can start from N_0 = N and stay greater than 1.