我有一个std::uint32_t
,想检查是否正好设置了一个位。我如何才能做到这一点,而不像这样迭代所有位?换句话说,下面的函数可以简化吗?
static inline bool isExactlyOneBitSet(std::uint32_t bits)
{
return ((bits & 1) == bits
|| (bits & 1 << 1) == bits
|| (bits & 1 << 2) == bits
// ...
|| (bits & 1 << 31) == bits
);
}
额外的好处:如果返回值是找到的位或者0,那就太好了。
static inline bool isExactlyOneBitSet(std::uint32_t bits)
{
if (bits & 1) {return 1;}
else if (bits & 1 << 1) {return 1 << 1;};
//...
else if (bits & 1 << 31) {return 1 << 31;};
return 0;
}
3条答案
按热度按时间odopli941#
所以你想知道一个数是否是2的幂,有一个著名的算法,你可以简单地做,
2的任何幂减1时都是
1s
。例如,2的任何幂和小于它的任何数1的按位与将给予
0
。因此,我们可以通过使用表达式n&(n-1)
来验证一个数是否是2的幂。当
n=0
时,它将失败,因此我们必须添加一个额外的and
条件。为了找到位的位置,您可以执行以下操作:
多余的东西
在gcc中,你可以使用
__builtin_popcount()
来查找任何数字中的设置位的计数。然后检查count是否等于
1
。关于count,还有一个著名的算法,Brian Kernighan的算法。谷歌一下,它在
log(n)
时间内找到count。n9vozmp42#
下面是你的附加问题的解决方案(当然,它也是你原来问题的解决方案):
这在x86_64上只编译了4条指令,并带有clang:
yfwxisqw3#
给定一个数字
n
,下面的表达式将确定是否正好设置了一个位(在任何语言中):(n & (n - 1)) == 0
.要检查一个数字是否是2的正幂,也可以使用表达式
(n & (-n)) == n
。然而,在JavaScript中,这些表达式在
-2^31
处失败。注意这里的按位AND(
&
)运算符。