从C+中的int中提取n个最高有效非零位+;无环 我想从C++中的整数中提取N个最重要的位,并将这些N位转换成整数。

从C+中的int中提取n个最高有效非零位+;无环 我想从C++中的整数中提取N个最重要的位,并将这些N位转换成整数。,c++,binary,bit,significant-digits,C++,Binary,Bit,Significant Digits,比如说 int a=1200; // its binary representation within 32 bit word-size is // 00000000000000000000010010110000 现在我想从该表示中提取4个最重要的数字,即1111 00000000000000000000010010110000 ^^^^ 并将它们再次转换为整数(十进制中的1001=9) 如何用简单的C++函数实现循环,不带循环?< p>它不快,但

比如说

int a=1200;
// its binary representation within 32 bit word-size is
// 00000000000000000000010010110000
现在我想从该表示中提取4个最重要的数字,即1111

00000000000000000000010010110000
                     ^^^^
并将它们再次转换为整数(十进制中的1001=9)


如何用简单的C++函数实现循环,不带循环?

< p>它不快,但是<代码>(int)(log(x)/log(2)+ 5)+1 < /C>会告诉你最重要的非零位的位置。从那里完成算法相当简单。

有些处理器有一条指令来计算整数的前导二进制零,有些编译器有指令来允许您使用该指令。例如,使用GCC:

uint32_t significant_bits(uint32_t value, unsigned bits) {
    unsigned leading_zeros = __builtin_clz(value);
    unsigned highest_bit = 32 - leading_zeros;
    unsigned lowest_bit = highest_bit - bits;

    return value >> lowest_bit;
}
为了简单起见,我省略了检查请求的位数是否可用。对于Microsoft的编译器,内部代码称为
\uuuzcnt

如果您的编译器没有提供这种内在特性,并且您的处理器没有合适的指令,那么快速计算零的一种方法是使用二进制搜索:

unsigned leading_zeros(int32_t value) {
    unsigned count = 0;
    if ((value & 0xffff0000u) == 0) {
        count += 16;
        value <<= 16;
    }
    if ((value & 0xff000000u) == 0) {
        count += 8;
        value <<= 8;
    }
    if ((value & 0xf0000000u) == 0) {
        count += 4;
        value <<= 4;
    }
    if ((value & 0xc0000000u) == 0) {
        count += 2;
        value <<= 2;
    }
    if ((value & 0x80000000u) == 0) {
        count += 1;
    }
    return count;
}
无符号前导零(int32\t值){
无符号计数=0;
如果((值&0xffff0000u)==0){
计数+=16;
value这似乎有效(用C#完成,带有UInt32,然后移植,因此向Bjarne道歉):

我想你的意思是只使用整数数学


我使用了@OliCharlesworth链接中的一些代码,您也可以通过在那里使用尾随零代码的LUT来删除条件。

强制链接:。您正在查找以1位开头的前n位。这与n个最高有效位不同。示例中的4个最高有效位都是0。据我所知,t什么是最重要的位。你忽略前导0,就好像它们不存在一样。也就是说,现在纯粹用十进制表示,12345000到2个有效数字是多少?00001234500怎么样?@BoBTFish:我的理解是,位(事实上,任何数字)越“左”越重要,不管是什么值(在本例中是零或一)是的。我认为越“左”越重要,因为改变数字比再向右改变数字更重要地改变了总值。@Ferruccio:“重要位”可能有两种含义,问题清楚地描述了这里的含义。谢谢,这绝对是我要找的函数!这正是我的意思。我将uint32_t类型修改为简单的int,因为我知道这里的整数大小是8字节。(p.s.在g++4.5 x86_64 Linux上编译)它涉及浮点运算…我不想使用浮点值。。。
        unsigned int input = 1200;
        unsigned int most_significant_bits_to_get = 4;
        // shift + or the msb over all the lower bits
        unsigned int m1 = input | input >> 8 | input >> 16 | input >> 24;
        unsigned int m2 = m1 | m1 >> 2 | m1 >> 4 | m1 >> 6;
        unsigned int m3 = m2 | m2 >> 1;
        unsigned int nbitsmask = m3 ^ m3 >> most_significant_bits_to_get;

        unsigned int v = nbitsmask;
        unsigned int c = 32; // c will be the number of zero bits on the right
        v &= -((int)v);
        if (v>0) c--;
        if ((v & 0x0000FFFF) >0) c -= 16;
        if ((v & 0x00FF00FF) >0) c -= 8;
        if ((v & 0x0F0F0F0F) >0 ) c -= 4;
        if ((v & 0x33333333) >0) c -= 2;
        if ((v & 0x55555555) >0) c -= 1;

        unsigned int result = (input & nbitsmask) >> c;