任何人都可以解释这个按位函数来计算log(n)

时间:2015-04-16 04:49:55

标签: c logic bitwise-operators

int howManyBits(int x) {
    int concatenate;
    int bias;
    int sign = x >> 31;  //get the sign
    x = (sign & (~x)) | (~sign & x); 
    concatenate = (!!(x >> 16)) << 4;
    concatenate |= (!!(x >> (concatenate + 8))) << 3;
    concatenate |= (!!(x >> (concatenate + 4))) << 2;
    concatenate |= (!!(x >> (concatenate + 2))) << 1;
    concatenate |= x >> (concatenate + 1);
    bias = !(x ^ 0);
    return concatenate + 2 + (~bias + 1);

}

此代码用于计算表示2的补码中的整数n所需的最小位数,假设int数据类型用32位表示。假设右移是算术运算。

我知道基本方法是取n的日志库2,将其四舍五入,然后添加1位以考虑符号位。

我也明白左移相当于乘以2而右移相当于除以2.

话虽如此,没有注释我无法解释这段代码在获取符号位值的部分之外的作用。我使用值为5的样本int在铅笔和纸上完成了它 - 代码有效,但我不明白为什么。

有人可以提供代码正在做什么的直观细分吗?

1 个答案:

答案 0 :(得分:4)

此代码可以使用一些注释。

如果它是正数,则保留x,如果是负数,则保留一个补码。这允许计算搜索最重要的一个,无论正面还是负面

x = (sign & (~x)) | (~sign & x);

我认为以下内容会更清楚:

x = sign ? ~x : x;

接下来是搜索使用二进制搜索完成的最高1位。首先搜索单词的上半部分。

concatenate = (!!(x >> 16)) << 4;

如果上半部分为1,则结果为16.后面的16作为答案的一部分使用,但也用于确定下一步搜索的位置。由于它在后面的班次中使用,因此将导致以下测试要么使用板的上半部分还是下半部分。

以下连接操作正在搜索原始数字逐渐变小的部分,看起来是所选择的16位的高8位或低8位中最重要的一位,然后是高4位或更低位选择的8位中的4位,依此类推。

concatenate |= (!!(x >> (concatenate + 8))) << 3; // Check which 8 bits
concatenate |= (!!(x >> (concatenate + 4))) << 2; // Check which 4 bits
concatenate |= (!!(x >> (concatenate + 2))) << 1; // Check which 2 bits
concatenate |= x >> (concatenate + 1);            // Check which 1 bit

偏见只是检查数字是否为0。仅当x为0时才为1.我不理解对XOR运算符的需要。

最后将这些碎片加在一起。