Java位操作快速指南 (Dev Genius)


位操作是对数据位进行操作的直接操作,并且是FAANG招聘人员目前测试的一项重要的优化技能。但是,该主题涉及大量数学知识,在非大学计算机科学领域很少涉及。
今天,我们将为您提供有关位操作的教程,并探讨一些常见的面试问题的动手实践。
 
什么是位操作?
位操作是对位序列(计算机中最小的数据形式)进行逻辑运算以获得所需结果的过程。位操作具有恒定的时间复杂度和并行处理,这意味着它在所有系统上都非常有效。
大多数编程语言都会让您处理抽象,例如对象或变量,而不是它们所代表的位。但是,在某些情况下需要直接位操作以提高性能并减少错误。
位操作需要对二进制和二进制转换有深入的了解。
以下是一些需要位操作的任务示例:

  • 低级设备控制
  • 错误检测和纠正算法
  • 资料压缩
  • 加密算法
  • 优化

例如,看一下算术和位处理方法之间的区别,以找到RGB值的绿色部分:
//算术
(RGB / 256)%256
//位
(rgb >> 8)&0xFF

尽管两者都做同样的事情,但是第二种方法要快得多,因为它直接在内存中而不是通过抽象级别起作用。
我们将在本文后面的(>>和&)中探讨这些运算符各自的作用。
 
按位操作和编码面试
在进行编程面试时,尤其是在FAANG公司中,位操作也是一个常见的话题。这些是面试者希望您对位,基本的位运算符有基本的了解,并且通常了解位操作背后的思维过程。
掌握了这些知识就可以证明您是一名全面的开发人员,同时了解计算机科学的特定工具和基础。
如果您要申请一个可与嵌入式系统或其他低级系统一起使用的角色,则会遇到更多问题。简而言之,您的角色越接近机器级别,您将遇到的位操作问题就越多。
准备位操作问题的最佳方法是练习使用每个按位运算符,然后再进行二进制到十进制的转换。
 
按位运算符
按位运算采用一个或多个位模式或二进制数字,并在位级别上对其进行操作。从本质上讲,它们是我们操纵位以实现操作的工具。
算术运算对人类可读的值(1+2)进行运算时,按位运算符可直接操纵低级数据。
好处
  • 它们是快速而简单的动作。
  • 它们由处理器直接支持。
  • 它们用于操纵值以进行比较和计算。
  • 与算术运算相比,按位运算非常简单且速度更快。

让我们快速看一下每个主要的Bitwise运算符及其用法。
 
AND运算符
AND(&)是一个二进制运算符,用于比较两个相等长度的操作数。操作数从其可读形式转换为二进制表示形式。对于每个位,该操作都会检查跨两个操作数的两个位是否都是1。如果是,则将答案中的该位设置为1。否则,将相应的结果位设置为0.
实际上,它会将每个位乘以另一个操作数中的相应位。将任何东西乘以0结果是0,与任何0位的AND比较将得出结果0。
  • 如果两个输入位为1,则输出为1。
  • 在所有其他情况下,其值为0,例如:
  • 1 & 0 =>得出0。
  • 0 & 1 =>得出0。
  • 0 & 0 =>得出0。

0101(十进制5)
AND 0011(十进制3)
0 * 0 = 0
1 * 0 = 0
0 * 1 = 0
1 * 1 = 1
Therefore:
= 0001 (decimal 1)

这种操作可用于确定是将特定位设置为(1)还是将其清除(0)。它还用于清除寄存器的选定位,其中每个位代表一个单独的布尔状态。

class AndOperation {
    public static void main( String args[] ) {
        int x = 12;
        int y = 10;
        System.out.println("Bitwise AND of (" + x + " , " + y + ") is: " + (x & y)); // yields to 8
    }
}

OR运算符
OR运算符(|)是一个二进制运算符,它采用两个等长的操作数,但以与AND相反的方式比较它们;如果对应的一位是1,答案是1。否则,答案将是0。换句话说,如果给定的输入之一为1,则按位或运算将返回“ 1” 。

  • 如果有两个输入位0,则输出为0。
  • 在其他所有情况下为1。例如:
  • 1 | 0 =>得出1。
  • 0 | 1 =>得出1。
  • 1 | 1 =>得出1。

a = 12 
b = 10 
--------------------------------- 
a(二进制):0000 0000 0000 1100 
b(二进制) :0000 0000 0000 1010 
--------------------------------- 
a | b:0000 0000 0000 1110 

这通常用作解决其他问题的临时逻辑步骤:

class OROperation {
    private static int helper(int x, int y) {
        return x | y;
    }
    public static void main(String[] args) {
        int x = 12;
        int y = 10;
        System.out.println("Bitwise OR of " + x + ", " + y + " is: " + helper(x, y)); // yields to 14
    }
}

 
NOT运算符
NOT(~)或有时称为按位补码运算符,是一元操作,它接受单个输入并将其二进制表示形式的每个位交换为相反的值。
 
异或运算符
按位XOR运算(^)是“ Exclusive-Or”的缩写,是一种二进制运算符,它接受两个输入自变量并比较每个对应的位。如果这些位相反,在该位的位置有一个结果1,如果它们匹配,则返回0。
  • 1 ^ 1 =>得出0。
  • 0 ^ 0 =>得出0。
  • 1 ^ 0 =>得出1。
  • 0 ^ 1 =>得出1。

案例:
a = 12
b = 10
--------------------------------------
a in binary : 0000 0000 0000 1100
b in binary : 0000 0000 0000 1010
--------------------------------------
a ^ b       : 0000 0000 0000 0110
--------------------------------------

XOR用于反转寄存器中选定的单个位或处理表示布尔状态的位模式。
XOR有时也用于将注册表的值设置为零,因为与两个相同输入的XOR总是会产生0。

class XOROperation {
    public static void main( String args[] ) {
        int x = 12;
        int y = 10;
        System.out.println("Bitwise XOR of (x , y) is : " + (x ^ y)); // yields to 6
    }
}

(据调查,异或逻辑在高级编程中很少应用到,但是在人们语言交流中经常存在。)
 
左右移位运算符
比特移位是按位操作,其中一个位序列的顺序被移动到有效地进行数学运算。移位将数字的二进制表示形式中的每个数字向左或向右移动第二个操作数指定的多个空格。
这些操作符可以应用于整数类型,例如int,long,short,byte,或char。

有三种类型的班次:

  • 左移: <<是左移运算符,可满足逻辑和算术移位的需求。
  • 算术/有符号右移: >>是算术(或有符号)右移运算符。
  • 逻辑/无符号右移: >>>是逻辑(或无符号)右移运算符。

class LeftShift { 
    private static int helper(int number,int i){
        返回数字<< i; //将'number'乘以2 ^ i倍。
    } 
    public static void main(String [] args){ 
        int number = 100; 
        System.out.println(number +“向左移动1个位置,产生为” + helper(number,1))); 
        System.out.println(number +“向左移动2个位置,产生为” + helper(number,2));
        System.out.println(number +“向左移动3个位置,生成为” + helper(number,3));
        System.out.println(number +“向左移动4个位置,产生为” + helper(number,4));
    } 
}

使用右移,您可以进行算术(>>)或逻辑(>>)移位。
区别在于算术移位保持相同的最高有效位(MSB)或符号位,即最左位,它确定一个数字是正数还是负数。
1011 0101 >> 1 = **1**101 1010

公式: x >> y = x/(2^y)
另一方面,逻辑移位只是将所有内容移至右侧,并用0代替MSB 。
1011 0101 >>> 1 = 0101 1010

公式: a >>> b = a/(2^b)