检查整数中是不是只设置了一个位(无论其位置如何)

Posted

技术标签:

【中文标题】检查整数中是不是只设置了一个位(无论其位置如何)【英文标题】:Check if only one single bit is set within an integer (whatever its position)检查整数中是否只设置了一个位(无论其位置如何) 【发布时间】:2012-11-16 16:10:00 【问题描述】:

我使用 64 位整数中的位存储标志。 我想知道在 64 位整数中的位置是否设置了一个位(即我不关心任何特定位的位置)。

boolean isOneSingleBitSet (long integer64)

   return ....;

我可以使用Bit Twiddling Hacks (by Sean Eron Anderson) 计算位数,但我想知道仅检测是否设置了一个位的最有效方法是什么...

我发现了一些其他相关的问题:

(8051) Check if a single bit is set Detecting single one-bit streams within an integer

还有一些***页面:

Find first one Bit manipulation Hamming weight

注意:我的应用程序是用 java 编写的,但我对使用其他语言的优化感到好奇...


编辑:Lưu Vĩnh Phúc 指出我的问题中的第一个链接已经得到了答案:请参阅 Bit Twiddling Hacks 中的 Determining if an integer is a power of 2 部分(作者 Sean Eron安德森)。我没有意识到一位二的幂是一样的。

【问题讨论】:

对于 Java,我会考虑为此目的使用 BitSet 类,它支持方便的 isEmpty() 方法以及许多其他使位标志更易于使用的方法。 它已经在上面链接的 Bit Twiddling Hacks 中:Determining if an integer is a power of 2 哦!谢谢 :-) 我更新了我的问题 :-) 干杯 这能回答你的问题吗? How to check if a number is a power of 2 【参考方案1】:

如果您只是想检查是否设置了一个位,那么您实际上是在检查该数字是否是 2 的幂。要做到这一点,您可以这样做:

if ((number & (number-1)) == 0) ...

这也将 0 视为 2 的幂,因此如果这很重要,您应该检查数字是否不是 0。那么:

if (number != 0 && (number & (number-1)) == 0) ...

【讨论】:

对不起,我已经测试了你的答案,我有这些结果:0->false (ok) ; 1->true (ok) ; 2->false (KO) ; 3->false (ok) ; 4->false (KO) 5->false (ok) ...请你也检查一下吗? 看看第二个版本,我已经详细说明了检查 != 0 的效果。就我所见,真的很好。 感谢您的编辑,但您的第一行 if ((number & (number-1)) == 0) ... 不检查 number 是否为 2 的幂,正如您在我的测试结果中看到的那样(请参阅我之前的评论)。要检查 number 是否是 2 的幂,您可以执行以下操作:if (number && !(number & (number - 1)) ...(请在您的回答中接受我的编辑) 不是在 Java 中你不能。在 C 中,你写的那行基本上和我写的一样。如果您想要与 C 而不是 Java 相关的答案,请相应地修改并重新标记您的问题。 好的,虽然我确实口头说过你需要进行零检查:你真的无法将其转化为代码吗??【参考方案2】:

(使用 x 作为参数)

检测是否设置了至少一位很容易:

return x!=0;

同样检测第一个位(第二个最低位)是否设置很容易:

return (x&2)!=0;

如果它是 2 的幂,则恰好设置了一位。这有效:

return x!=0 && (x & (x-1))==0;

【讨论】:

有什么方法可以检查哪个位在吗? (在日志旁边)顺便说一句很棒的技巧 @hl3mukkel 您可以使用迭代除法(这只是一种计算整数对数的方法)。如果您正在寻找更快的东西,请查看***.com/q/14429661/499214。使用对数肯定更具可读性,但会出现舍入问题。 谢谢!我发现link 是一种高效且干净的方法。【参考方案3】:

包装类java.lang.Long有一个静态函数bitCount(),它返回long(64位int)中的位数:

boolean isSingleBitSet(long l)

     return Long.bitCount(l) == 1;

请注意,int 在 java 中是 32 位的。

【讨论】:

将条件更改为 ==1,这将起作用,但严格来说,它几乎肯定不是检测单个位的最有效方法。 你知道这个方法的开销吗?这当然是最易读的解决方案,即使不是最快的。 现在 (>0),这将检查数字是否非零(感谢 @NeilCoffey 的注意)。 +1 对于这个可读的解决方案。有没有检查整数是否是2的幂的函数? Jan - 我猜,仅从操作的数量来看,它基本上会比我在回答中提到的通常方法慢几倍。至于可读性,你可以将任何你想要的实现包装在一个名为 isSingleBitSet() 的方法中——我不确定从这个角度来看它有什么不同......【参考方案4】:

让我们假设 X 是一个 64 位的全 0,除了你要找的那个;

  return ((64bitinteger&X)==X)

【讨论】:

64bitinteger = 0 时返回 true :-( 您的答案中的X 是什么?同64bitinteger? 1010101 如果要检查第 3 位是否为 1 1010101 & 0010000 在此示例中等于 0010000 X=0010000 感谢您的回答,但我正在寻找最有效的方法来了解是否在任何位置设置了单个位...【参考方案5】:

假设您已经有ffs() 的高效(或硬件)实现 - 找到第一个集合 - 您可以执行以下操作:

bool isOneSingleBitSet (long integer64)

   return (integer64 >> ffs(integer64)) == 0;

ffs() 功能可能已经可用,或者您可能想查看your own link above

【讨论】:

ffs() 在 java 中可用吗? +1 你的答案是有效的 :-) 但使用 GCC __builtin_ffs() 进行了测试。请告诉我ffs() 在 java 中是否可用... 我不是java开发者!只是对您的问题感兴趣【参考方案6】:

似乎您可以对要检查的单个位的long 表示进行按位与运算。例如,检查 LSB

return(   (integer64 & 1L)!=0  );

或者检查右数第四位

return(   (integer64 & 8L)!=0  );

【讨论】:

好的...但是您如何检查是否设置了一个位?你检查每个 64 位吗? 使用这个答案中的方法,是的,但我不推荐它。我将最初的问题理解为检查特定位,而不是按预期检查任何单个位。正如您所想,这个问题更有趣,Neil Coffey 和 Jan Dvorak 回答得很好。 感谢@Pursuit。我会改进一下我的问题以便更容易理解;-)

以上是关于检查整数中是不是只设置了一个位(无论其位置如何)的主要内容,如果未能解决你的问题,请参考以下文章

在检查指定位置是不是设置位时,右移数字和左移位掩码哪个更好?

如何检查位置设置是不是在更改时失败

GPS Android - 只定位一次

检查 locationServicesEnabled 始终返回 YES,无论手动拨动开关决定是不是启用了位置服务

是否有一个签名值的技术术语,其中只设置了最高位?

iphone app - 如何只获取一次当前位置并将其存储以用于另一个功能?