[英]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.