Basically you are trying to calculate: floor(log2(x))
Take the logarithm to base 2, then take the word.
The most portable way to do this in C is to use the logf()
function, which finds the log in the e database and then configures: log2(x) == logf(x) / logf(2.0)
See the answer here: How to write a database (2) in c / C ++
If you just pass the resulting float value to int
, you evaluate floor()
at the same time.
But if this is available to you and you can use it, there is a very fast way to calculate log2()
floating point numbers: logbf()
On the man page:
The inte- ger constant FLT_RADIX, defined in <float.h>, indicates the radix used for the system floating-point representation. If FLT_RADIX is 2, logb(x) is equal to floor(log2(x)), except that it is probably faster.
http://linux.die.net/man/3/logb
If you think about how floating point numbers are stored, you understand that the value of floor(log2(x))
is part of the number, and if you just extract that value, you're done. A bit biasing and bit-masking, and subtract the bias from the exponent (or technically the βvalueβ), and there you have it. The fastest way to calculate floor(log2(x))
for any float x
value.
http://en.wikipedia.org/wiki/Single_precision
But in fact, logbf()
converts the result to a float before passing it and handles the errors. If you write your own function to extract the exponent as an integer, it will be a little faster, and the integer will be what you want anyway. If you want to write your own function, you need to use C union
to access the bits inside the float; When you try to play with pointers, you will get warnings or errors related to the "type", at least on the GCC. I will give details on how to do this, if you ask. I wrote this code before as an inline
function.
If you only have a small range of numbers to test, you can overlay numbers on an integer, and then use the lookup table.