问题
What is an efficient method to calculate the integer part of the base 2 logarithm of a floating point number? Something like
N = ceil( log2( f ))
or
N = floor( log2( f ))
for floating point f. I guess this is possible to realize very efficiently somehow as one probably only needs access to the floating point exponent.
EDIT2: I am not primarily interested in exactness. I could tolerate an error of +-1. I listed the two variants just as an example because one might be computationally cheaper than the other (but I dont know).
I need this for accuracy control of an algorithm where the parameter f is some tolerance and the log is needed to control the number of terms. Accurate calculation of the log is not important.
EDIT: this is not a duplicate of other the many other questions asking for the log2 of an integer argument (e.g. How to do an integer log2() in C++?) . This here is about floating point argument and a completely different story. Specifically I need it for f < 1, which is not possible at all with the integer methods
回答1:
The standard library function frexp does exactly that: it decomposes a double into an integer exponent and a normalized mantissa.
If you are content with the floor of the logarithm, rather than rounding the logarithm to the nearest integer, you are probably better off with the newer standard library function ilogb.
Note that these two functions treat zeros and infinities differently, so they are not quite interchangeable.
回答2:
Inspired by rici, who pointed me to frexp, I think I found the answer. In C99 and recent C++ we have the function ilogb which does exactly that what I need
int ilogb( float arg );
int ilogb( double arg );
and is equivalent to
(int)logb( arg )
It returns one less than frexp. So the frexp result corresponds to
floor(log2(arg)+1
and ilogb(arg) to
floor(log2(arg))
回答3:
This is a horrible hack which extracts the exponent from the little-endian float
although I make no guarantee about portability, etc.
#include <stdio.h>
int main(void) {
float f;
unsigned i;
unsigned *ip = (unsigned*)&f;
printf("Enter a float: ");
scanf("%f", &f);
i = *ip;
i = (i >> 23) & 0xFF;
i -= 127;
printf("%f %d\n", f, (int)i);
return 0;
}
Program output:
Enter a float: 0.125
0.125000 -3
来源:https://stackoverflow.com/questions/39336542/quickly-find-the-integer-part-of-the-base-2-logarithm