zoukankan      html  css  js  c++  java
  • 移位、位与、或、异或、非

    Java位运算符有:左移( << )、右移( >> ) 、无符号右移( >>> ) 、位与( & ) 、位或( | )、位非( ~ )、位异或( ^ ),除了位非( ~ )是一元操作符外,其它的都是二元操作符。

    原码、反码、补码

    原码:一个整数,按照绝对值大小转换成的二进制数,称为原码。

    00000000 00000000 00000000 00000101   是5的原码
    

    反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码。即:1变0; 0变1

    11111111 11111111 11111111 11111010   是5的反码
    

    补码:反码加1称为补码。

    11111111 11111111 11111111 11111011   是5的补码
    

    在学习位移之前,我们先了解负数二进制的表示,你可能听过两种不同的回答。

    一种是教科书,它会告诉你:计算机用“补码”表示负数。例如上面5的补码:11111111 11111111 11111111 11111011表示-5

    另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数。这种说法本身没错,可是如果没有下文,那么它就是错的。至少它不能解释,为什么字符类型的-1用二进制表示是“1111 1111”(16进制为FF);而不是我们更能理解的“1000 0001”。(为什么说后者更好理解呢?因为既然说最高位是1时表示负数,那1000 0001不是正好是-1吗?

    其实对于计算机来说没有正负二进制之分,比如一个8位的二进制1111 1001,即可以表示-7,也可以表示249,最终得到的结果是正是负取决于开发者本人如何定义这个变量(数据的类型,比如int,unsigned,long,double等等),如果你定义的是一个负值,则补码先减1得到反码1111 1000,然后反码取反得到原码0000 0111,原码转换二进制为7,由于你定义的是一个负数则添加负号得到-7返回

    左移(<<)

    先看一个例子:5左移2位

    public class DisplacementOperatorTest {
        public static void main(String[] args) {
            // 5左移2位的结果为20
            System.out.println(5 << 2);
        }
    }
    

    下面是具体操作过程(Java整数默认int类型,二进制为32位):

    5的二进制:
    0000 0000 0000 0000 0000 0000 0000 0101
    
    左移2位,低位补0后,得到:
    0000 0000 0000 0000 0000 0000 0001 0100
    
    换算成10进制为:20
    

    右移(>>)

    先看一个例子:5右移2位

    public class DisplacementOperatorTest {
        public static void main(String[] args) {
            // 5右移2位的结果为1
            System.out.println(5 >> 2);
        }
    }
    

    下面是具体操作过程(Java整数默认int类型,二进制为32位):

    5的二进制:
    0000 0000 0000 0000 0000 0000 0000 0101
    
    右移2位,高位补0后,得到:
    0000 0000 0000 0000 0000 0000 0000 0001
    
    换算成10进制为:1
    

    无符号右移(>>>)

    • 正数右移,高位补0
    • 正数左移,低位补0
    • 负数右移,高位补1
    • 负数左移,低位补0
    • 负数无符号右移,高位补0
    • 负数没有无符号左移

    先看一个例子:

    public class DisplacementOperatorTest {
        public static void main(String[] args) {
            //结果是0
            System.out.println(5 >> 3);
    
            //结果是-1
            System.out.println(-5 >> 3);
    
            //结果是536870911
            System.out.println(-5 >>> 3);
        }
    }
    

    下面是具体操作过程(Java整数默认int类型,二进制为32位):

    5的二进制:
    0000 0000 0000 0000 0000 0000 0000 0101
    
    5右移3位,高位补0后,换算成十进制得0:
    0000 0000 0000 0000 0000 0000 0000 0000
    
    -5得二进制:
    1111 1111 1111 1111 1111 1111 1111 1011
    
    -5右移3位,高位补1后,换算成十进制得-1
    1111 1111 1111 1111 1111 1111 1111 1111
    
    -5无符号右移3位,高位补0后,换算成十进制得536870911
    

    位与(&)

    第一个操作数的的第n位于第二个操作数的第n位如果都是1,那么结果的第n为也为1,否则为0

    5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
    3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
    
    1转换为二进制:0000 0000 0000 0000 0000 0000 0000 0001
    

    位或(|)

    第一个操作数的的第n位于第二个操作数的第n位 只要有一个是1,那么结果的第n为也为1,否则为0

    5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
    3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
    
    7转换为二进制:0000 0000 0000 0000 0000 0000 0000 0111
    

    异或(^)

    第一个操作数的的第n位于第二个操作数的第n位 相反,那么结果的第n为也为1,否则为0

    5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
    3转换为二进制:0000 0000 0000 0000 0000 0000 0000 0011
    
    6转换为二进制:0000 0000 0000 0000 0000 0000 0000 0110
    

    位非(~)

    操作数的第n位为1,那么结果的第n位为0,反之

    5转换为二进制:0000 0000 0000 0000 0000 0000 0000 0101
    
    -6转换为二进制:1111 1111 1111 1111 1111 1111 1111 1010
    
  • 相关阅读:
    详解 注解
    线段树分治
    实用Trick
    CF932F(李超线段树+dp)
    CF24D Broken robot(高斯消元)
    LCT学习笔记
    [HNOI2008]GT考试
    [AHOI2009]中国象棋
    [APIO2012]派遣
    CF961G Partitions
  • 原文地址:https://www.cnblogs.com/kesuns/p/12255160.html
Copyright © 2011-2022 走看看