为什么我们在2个数字之间使用按位运算符?

时间:2017-01-08 23:01:51

标签: java bitwise-operators

根据以下信息,我不明白为什么你想要评估,例如,使用&运算符的2个十六进制整数。我理解下面解释的反演模式,我可以自己计算,但很难推断为什么(从我在互联网上看到的帖子)。什么是真实世界场景可能会让我在这里有所见解?

  0xff00 & 0xf0f0 is 0xf000
  0xff00 ^ 0xf0f0 is 0x0ff0
  0xff00 | 0xf0f0 is 0xfff0
For &, the result value is the bitwise AND of the operand values.
For ^, the result value is the bitwise exclusive OR of the operand values.
For |, the result value is the bitwise inclusive OR of the operand values.

在我自己的脑海里,我现在想到这样:

if ( 65280 & 61680 )  // evaluates to 61440, not boolean?

3 个答案:

答案 0 :(得分:9)

这些类型的运算符用于很多事情,但是现在在更高级别的语言中,它们最常用于标记。它是来自C等低级语言的延续,其中内存分配和释放并不总是微不足道的,而且是在硬件资源稀缺的时候开发的。

假设某些操作有3个可能的标志,并且可以在任何给定的组合中提供它们。提供标志的快速,简单且有效的方法是将每个标志分配给整数位。

public static final int FLAG_1 = 1;       // 00000001
public static final int FLAG_2 = 1 << 1;  // 00000010
public static final int FLAG_3 = 1 << 2;  // 00000100

然后发送多个标志,我可以使用按位或&#34; |&#34;运营商。

someFunc(FLAG_1 | FLAG_3).

要读取传递的标志,我可以使用按位&amp;操作

public void someFunc(int flags) {
    if ((flags & FLAG_1) == FLAG_1 /*Or (flags & FLAG_1) != 0 */) { 
      // Passed in flag 1.
    }
}

还有其他方法可以做到这一点,但这非常有效,易于阅读,并导致堆上的零对象分配。如果你想到用Java完成这个的其他方法,让我们说一个枚举/整数的数组或集合,或者每个标志是一个单独的方法参数,它清楚为什么这个而是使用模式。

答案 1 :(得分:2)

我认为如果您需要实现一小部分boolean,最好将其表示为intlong,每个位代表一个数组元素:

  • 如果有大量的数组,那么内存使用是一个问题;或
  • 如果您正在进行大量计算。

在这种情况下,您可以使用移位运算符和&|&=|=^=进行测试,清除,设置或翻转数组的元素。 (另请注意,这可以并行使用多个数组元素。)

这种情况很少发生。为了便于阅读,使用常规arrayArrayList要好得多。但是,我有两个用例至少出现一次。一个是使用强力回溯算法编写数独求解器;我不记得细节,但我想我使用9位int来表示行,列或方形中的单元格是否被占用。如果我没记错的话,我的一些代码会同时测试多个单元格,我可以使用一个&运算符。由于通过回溯解决可能涉及大量的组合,我相信使用这种机制在运行时间方面产生了明显的差异。另一个案例涉及一个项目表,用于保存项目是否具有某些属性的信息。物业数量相对较少(10至20之间),但物品数量可能达到数千万。 Set可能是表示属性集的自然选择,但由于我需要保留大量的HashSet,因此需要记忆。

除非内存或时间有很大差异,否则我不建议这样做。它有点“棘手”,我更喜欢直截了当的代码来表达你想要完成的事情。

答案 2 :(得分:1)

对于if语句中的一个非常基本的例子:

if ( (65280 & 1) == 0 ){
  // 65280 is even!
}
    如果x & 1是,则
  • 0x 如果x & 1为奇数,
  • 1x