【问题标题】: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) 计算位数,但我想知道仅检测是否设置了一个位的最有效方法是什么...

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

还有一些维基百科页面:

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


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

【问题讨论】:

标签: java binary bit-manipulation bit bitwise-operators


【解决方案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 您可以使用迭代除法(这只是一种计算整数对数的方法)。如果您正在寻找更快的东西,请查看stackoverflow.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。我会改进一下我的问题以便更容易理解;-)
猜你喜欢
  • 1970-01-01
  • 2018-12-08
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多