Java:长时间检查某位是0还是1


Answers:


180

我会用:

if ((value & (1L << x)) != 0)
{
   // The bit was set
}

(您也许可以用更少的括号摆脱掉,但我不记得按位运算的优先级。)


53
这取决于语言。在Java中不是这样。
harmanjd

12
那应该是1L,或者(1 << 32)最终与(1 << 0)的值相同
mkb

4
@ThibThib对此并不奇怪。请不要发布愚蠢的反Java火焰诱饵。
amischiefr

12
我想知道((value >>> x)&1)!= 0是否更好是因为值长还是短都无关紧要,还是因为它不那么明显而差呢?
Tom Hawtin-抢险

4
@ArtOfWarfare:有时我误输入===-导致分配该值的有效表达式,这不是我想要的。在Java中,这是非法的(假设它不是boolean变量)。按位运算符是Java的一部分,这对IMO来说是一件好事。在很多情况下,您需要按位运算符。有没有需要混为一谈,与是否没有条件表达式的类型whileif等等应该是boolean-我认为它应该。
乔恩·斯基特

97

另一种选择:

if (BigInteger.valueOf(value).testBit(x)) {
    // ...
}

39
+1使用将来的维护者可以理解的代码
cherouvim

9
如果经常调用此代码,则不是一个很好的解决方案。您正在用单行替代项替换单行替代项,并且位移位确实并不难。
wds

3
行的长度!=行的可读性,wds。您可能是对的,因为先前的解决方案效率更高,但是差异可能很小,尤其是如果内嵌testBit()时。
WCWedin

7
应该注意的是,该解决方案分配内存,并且效率远低于按位运算符。是的,这通常无关紧要,但是有时候,避免不必要的GC和/或低效的代码(Android应用程序,游戏主循环中的代码等)非常重要。
NateS

6
资源浪费。如果您不信任“未来维护者”来理解位操作,那么与项目上的人力资源相比,您将面临更大的问题。位操作不是魔术。这是程序员基本技能的一部分。
支石墓

15

我怀疑是否:

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

  }

..更好是因为值的长短与否无关紧要,或者因为值不那么明显而更差。

汤姆·霍顿(Tom Hawtin)-大头钉7月7日在14:16


我认为这会更好,因为发生错误的可能性较小-如果您认为错误不明显,则可以始终将测试提取到适当命名的函数中(布尔isBitSet(long value,int x)左右)
hjhill

12

您也可以使用

bool isSet = ((value>>x) & 1) != 0;

编辑:“ (value>>x) & 1”和“ value & (1<<x)”之间的区别取决于x大于“值”(在您的情况下为32)类型的大小时的行为。

在这种特殊情况下,使用“ (value>>x) & 1”会得到值的符号,而使用“ value & (1<<x)”会得到0 (如果x太大,获得位符号有时会很有用)。

如果您希望在这种情况下使用0,则可以使用“ >>>”运算符,如果使用“ >>

因此,“ ((value>>>x) & 1) != 0”和“ (value & (1<<x)) != 0”是完全等效的


8

对于n第LSB(最低有效位),应执行以下操作:

boolean isSet = (value & (1 << n)) != 0;

8
那应该是1L,否则(1 << 32)最终与(1 << 0)相同的值
mkb



4

在Java中,以下工作正常:

if (value << ~x < 0) {
   // xth bit set
} else {
   // xth bit not set
}

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

对于非Java程序员,请注意:前面的表达式在Java中有效,因为在该语言中,移位运算符仅适用long于右侧操作数的最低5位(如果为,则为6 )。此隐含地平移表达式value << (~x & 31)(或者value << (~x & 63)如果valueIS long)。

Javascript:它也可以在javascript中使用(就像Java,仅应用移位计数的最低5位)。在javascript中,任何number为32位。

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



2

如果某人对按位运算符不太满意,则可以尝试使用以下代码以编程方式确定它。有两种方法。

1)使用Java语言功能获取二进制格式的字符串,然后检查特定位置的字符

2)继续除以2并确定特定位置的位值。

public static void main(String[] args) {
    Integer n =1000;
    String binaryFormat =  Integer.toString(n, 2);
    int binaryFormatLength = binaryFormat.length();
    System.out.println("binaryFormat="+binaryFormat);
    for(int i = 1;i<10;i++){
        System.out.println("isBitSet("+n+","+i+")"+isBitSet(n,i));
        System.out.println((binaryFormatLength>=i && binaryFormat.charAt(binaryFormatLength-i)=='1'));
    }

}

public static boolean isBitSet(int number, int position){
    int currPos =1;
    int temp = number;
    while(number!=0 && currPos<= position){
        if(temp%2 == 1 && currPos == position)
            return true;
        else{
            temp = temp/2;
            currPos ++;
        }
    }
    return false;
}

输出量

binaryFormat=1111101000
isBitSet(1000,1)false
false
isBitSet(1000,2)false
false
isBitSet(1000,3)false
false
isBitSet(1000,4)true
true
isBitSet(1000,5)false
false
isBitSet(1000,6)true
true
isBitSet(1000,7)true
true
isBitSet(1000,8)true
true
isBitSet(1000,9)true
true

2
一个部门的成本比一位操作员的CPU时间多大约一百倍。然后您会反复进行。关于性能,此“解决方案”处于BigInteger级别。
Agoston Horvath'2

1

声明一个temp int并使它等于原始值。然后将temp >> x移位,以便要检查的位在最后一个位置。然后执行temp&0xf删除前面的位。现在剩下最后一点。最后,如果(y&1 == 0),如果最后一位是1,则应等于0,否则应等于1。如果不是(y + 0x1 == 0)...不太确定。鬼混看看


2
为什么您发布了一个令人费解的,难以理解的,虚假的答案,而现有答案却超过50个,却没有什么?
基思·品森

0

我的贡献-忽略上一个

public class TestBits { 

    public static void main(String[] args) { 

        byte bit1 = 0b00000001;     
        byte bit2 = 0b00000010;
        byte bit3 = 0b00000100;
        byte bit4 = 0b00001000;
        byte bit5 = 0b00010000;
        byte bit6 = 0b00100000;
        byte bit7 = 0b01000000;

        byte myValue = 9;                        // any value

        if (((myValue >>> 3) & bit1 ) != 0) {    //  shift 3 to test bit4
            System.out.println(" ON "); 
        }
    } 
}

0

我编码了一个静态类,它正在执行一些位操作。

public final class Bitfield {

  private Bitfield() {}

  // ********************************************************************
  // * TEST
  // ********************************************************************

  public static boolean testBit(final int pos, final int bitfield) {
      return (bitfield & (1 << pos)) == (1 << pos);
  }

  public static boolean testNum(final int num, final int bitfield) {
      return (bitfield & num) == num;
  }

  // ********************************************************************
  // * SET
  // ********************************************************************

  public static int setBit(final int pos, final int bitfield) {
     return bitfield | (1 << pos);
  }

  public static int addNum(final int number, final int bitfield) {
      return bitfield | number;
  }

  // ********************************************************************
  // * CLEAR
  // ********************************************************************

  public static int clearBit(final int pos, final int bitfield) {
      return bitfield ^ (1 << pos);
  }

  public static int clearNum(final int num, final int bitfield) {
      return bitfield ^ num;
  }

  }

如果有任何疑问,请给我写一封电子邮件。

好的编程!


-2

消除了移位及其复杂性,并为正确的操作数使用了LUTand


这比按位操作要慢得多。这将需要在1或2个时钟周期的按位操作中进行地址查找。
凯尔·法尔康纳
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.