quickly find the integer part of the base 2 logarithm

試著忘記壹切 提交于 2019-12-10 15:31:02

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!