views:

462

answers:

4

Is there any very fast method to find a binary logarithm of an integer number? For example, given a number x=52656145834278593348959013841835216159447547700274555627155488768 such algorithm must find y=log(x,2) which is 215. x is always a power of 2.

The problem seems to be really simple. All what is required is to find the position of the most significant 1 bit. There is a well-known method FloorLog, but it is not very fast especially for the very long multi-words integers.

What is the fastest method?

+9  A: 

Is this what you're looking for?

Christoffer Hammarström
Thanks! Very useful info.
psihodelia
Wow, most amazing collection of solutions I ever saw for a single problem, it's really impressive the level of details taken into consideration...
Matthieu M.
A: 

If the integers are stored in a uint32_t a[], then my obvious solution would be as follows:

  1. Run a linear search over a[] to find the highest-valued non-zero uint32_t value a[i] in a[] (test using uint64_t for that search if your machine has native uint64_t support)

  2. Apply the bit twiddling hacks to find the binary log b of the uint32_t value a[i] you found in step 1.

  3. Evaluate 32*i+b.

ndim
I don't believe a binary search will work here, since `a[]` is not sorted -- there will be 0-words both before and after the single word containing a single 1-bit.
j_random_hacker
Uhm. Of course. What was I thinking? Linear search will be the only thing to work there. I have updated the answer accordingly.
ndim
+1  A: 

The answer is implementation or language dependent. Any implementation can store the number of significant bits along with the data, as it is often useful. If it must be calculated, then find the most significant word/limb and the most significant bit in that word.

drawnonward
+3  A: 

A quick hack: Most floating-point number representations automatically normalise values, meaning that they effectively perform the loop Christoffer Hammarström mentioned in hardware. So simply converting from an integer to FP and extracting the exponent should do the trick, provided the numbers are within the FP representation's exponent range! (In your case, your integer input requires multiple machine words, so multiple "shifts" will need to be performed in the conversion.)

j_random_hacker