Java:检查长度为0或1

And*_*NER 70 java bit-shift long-integer

您将使用什么方法来确定表示2 ^ x的位是1还是0?

Jon*_*eet 167

我用的是:

if ((value & (1L << x)) != 0)
{
   // The bit was set
}
Run Code Online (Sandbox Code Playgroud)

(您可以使用更少的括号来逃避,但我永远不会记住按位运算的优先级.)

  • 这取决于语言.在java中不是真的. (52认同)
  • 那应该是1L,或者(1 << 32)最终得到与(1 << 0)相同的值 (12认同)
  • 我想知道((值>>> x)&1)!= 0是否更好,因为无论值是否很长都无关紧要,或者它是否更糟,因为它不太明显. (12认同)
  • @ArtOfWarfare:我有时会错误地将`=='写成`=` - 这会导致一个有效的表达式分配该值,这不是我想要的.在Java中,这是非法的(假设它不是`boolean`变量).按位运算符是Java的一部分,这是IMO的一件好事.在很多情况下你需要*按位运算符.没有必要把它与`while`,`if`等条件表达式的类型是否应该是`boolean`混淆 - 我相信它应该. (4认同)
  • @ThibThib对此一无所知.请不要发布愚蠢的反Java火焰诱饵. (3认同)
  • @Erich:我觉得更容易想到改变面具而不是改变价值.该问题更容易被描述为"比特x设置为1"而不是"是在最小比特中右移x比特1的值".我觉得个人品味.@Matt:固定,谢谢. (2认同)
  • ThibThib:s/strange /强类型/ (2认同)

fin*_*nnw 90

另一种选择:

if (BigInteger.valueOf(value).testBit(x)) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • +1使用未来维护者可以理解的代码 (35认同)
  • 如果要经常调用此代码,这不是一个很好的解决方案.你正在用一线替代品取代单线替代品,而且换位真的不是那么难. (9认同)
  • 应该注意,此解决方案分配内存,并且比按位运算符效率低得多.是的,它通常无关紧要,但有时避免不必要的GC和/或低效代码(Android应用程序,在游戏的主循环中等)非常重要. (6认同)
  • 资源浪费.如果你不能相信"未来的维护者"来理解位操作那么你就会遇到比项目人力资源更大的问题.位操作不是魔术.这是程序员技能基本集的一部分. (4认同)
  • 行长!=行的可读性,wds.您可能是正确的,以前的解决方案更有效,但差异可能很小,特别是如果testBit()内联. (3认同)
  • @dolmen,如果探查器强调它占用了大量的CPU时间,我会用更快的东西替换它.在那之前,没关系. (2认同)

And*_*NER 14

我怀疑是否:

  if (((value >>> x) & 1) != 0) {

  }
Run Code Online (Sandbox Code Playgroud)

..更好,因为价值是否很长无关紧要,或者更糟,因为它不太明显.

Tom Hawtin - 7月7日14:16发表讲话


Thi*_*hib 12

你也可以使用

bool isSet = ((value>>x) & 1) != 0;
Run Code Online (Sandbox Code Playgroud)

编辑:当"x"大于"值"类型(在您的情况下为32)的大小时," (value>>x) & 1"和" value & (1<<x)" 之间的差异依赖于行为.

在这种特殊情况下,使用" (value>>x) & 1",您将获得值的符号,而使用" value & (1<<x)" 获得0 (如果x太大,有时可以获得位符号).

如果您希望在这种情况下使用0,则可以使用" >>>"运算符,而不是" >>"

所以," ((value>>>x) & 1) != 0"和" (value & (1<<x)) != 0"完全等同


Nol*_*rin 8

对于n第LSB(最低有效位),以下应该起作用:

boolean isSet = (value & (1 << n)) != 0;
Run Code Online (Sandbox Code Playgroud)

  • 那应该是1L,或者(1 << 32)最终得到与(1 << 0)相同的值 (8认同)

rsl*_*mos 5

在 Java 中,以下工作正常:

if (value << ~x < 0) {
   // xth bit set
} else {
   // xth bit not set
}
Run Code Online (Sandbox Code Playgroud)

value并且x可以是intlong(并且不需要相同)。

对非 Java 程序员的警告long:前面的表达式在 Java 中有效,因为在该语言中,位移运算符仅适用于右侧操作数的5 个(或 6 个,如果是)最低位。这隐式地将表达式转换为value << (~x & 31)(或value << (~x & 63)if valueis long)。

Javascript:它也适用于 javascript(与 java 一样,仅应用移位计数的最低 5 位)。在 javascript 中,anynumber是 32 位的。

特别是在 C 中,负移位计数会调用未定义的行为,因此此测试不一定有效(尽管可能有效,具体取决于编译器/处理器的特定组合)。

它是如何工作的?

这个答案的巧妙之处在于,整数的符号位非常容易阅读:当该位被设置时,该值是负数;当该位被设置时,该值是负数。如果未设置,则该值为零或正数。

所以整个想法是将第 x 位精确地移入符号位。31 - x这意味着向左位移(或者63 - x,如果value是 64 位宽)。

在java(以及其他语言)中,~运算符计算按位NOT运算,它在算术上等于-x - 1(无论多宽x)。

此外,java<<运算符仅采用右侧操作数的最低有效 5(或 6)位(5 或 6 取决于左侧操作数的宽度:对于intthen 5;对于longthen 6)。从算术上讲,这与除以 32(或 64)的余数相同。

这就是(-x - 1) % 32= 31 - x(或(-x - 1) % 64= 63 - x,对于 64 位宽value)。