首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从C++中无循环的int中提取n个最高有效非零位

从C++中无循环的int中提取n个最高有效非零位
EN

Stack Overflow用户
提问于 2012-03-15 19:08:05
回答 3查看 4.4K关注 0票数 5

我想从C++中的整数中提取n个最高有效位,并将这n个位转换为整数。

例如

代码语言:javascript
复制
int a=1200;
// its binary representation within 32 bit word-size is
// 00000000000000000000010010110000

现在,我想从该表示中提取4个最重要的数字,即1111

代码语言:javascript
复制
00000000000000000000010010110000
                     ^^^^

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

一个没有循环的简单c++函数怎么可能实现呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-15 20:19:03

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

代码语言:javascript
复制
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;
}

为简单起见,我省略了检查请求的位数是否可用。对于微软的编译器,其内部特性称为__lzcnt

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

代码语言:javascript
复制
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;
}
票数 7
EN

Stack Overflow用户

发布于 2012-03-15 19:55:51

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

票数 1
EN

Stack Overflow用户

发布于 2012-03-15 21:01:26

这似乎是有效的(用UInt32在C#中完成,然后移植到Bjarne,非常抱歉):

代码语言:javascript
复制
        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;

我以为你的意思是只使用整数数学。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9718453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档