繁体   English   中英

关闭数字的最左边的非零位

[英]turning off leftmost non zero bit of a number

如何关闭O(1)数字的最左边non-zero位?

例如

n = 366 (base 10) = 101101110 (in base 2)

然后关闭最左边non-zero位后,数字看起来像 = 001101110

n 总是 >0

好吧,如果你坚持O(1)在任何情况下,英特尔内部函数功能_bit_scan_reverse()中定义immintrin.h做了硬件查找在INT数最显著非零位。

尽管该操作确实使用了循环(功能等效),但我相信它的时间恒定,因为它的延迟固定为 3(​​根据Intel Intrinsics Guide )。

该函数会将索引返回到最重要的非零位,从而执行一个简单的操作:

n = n & ~(1 << _bit_scan_reverse(n));

应该做。

对于 n == 0,这个内在函数是未定义的。所以你必须小心。 我遵循您原始帖子的假设,其中 n > 0。

n = 2^x + y. x = log(n) base 2

您的最高设置位是x

所以为了重置那个位, number &= ~(1 << x);

另一种方法:

int highestOneBit(int i) {
    i |= (i >>  1);
    i |= (i >>  2);
    i |= (i >>  4);
    i |= (i >>  8);
    i |= (i >> 16);
    return i - (i >> 1);
}

int main() {
    int n = 32767;
    int z = highestOneBit(n); // returns the highest set bit number i.e 2^x.
    cout<< (n&(~z)); // Resets the highest set bit.
    return 0;
}

使用处理器指令查看此问题,以获得可能更快的解决方案。

然而,一个 O(lgN) 的解决方案是:

int cmsb(int x)
{
    unsigned int count = 0;
    while (x >>= 1) {
        ++count;
    }

    return x & ~(1 << count);
}

如果不支持 ANDN 并且支持 LZCNT,那么最快的 O(1) 方法不是按照n = n & ~(1 << _bit_scan_reverse(n)); 反而...

int reset_highest_set_bit(int x)
{
    const int mask = 0x7FFFFFFF; // 011111111[...]

    return x & (mask >> __builtin_clz(x));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM