跳至主要內容

09-Java 中位运算符

AI悦创原创Java体系课Java体系课大约 7 分钟...约 1957 字

你好,我是悦创。本次课,先学:https://bornforthis.cn/posts/21.htmlopen in new window

0. 目录

  • 字面值的八进制和十六进制
  • 按位运算符
  • 位移运算符
  • 位运算符不会改变原变量的值
  • 位运算符用处

1. 字面值的八进制和十六进制

1.1 以 0 开头的整数为八进制

  • 05 就是十进制的 5
  • 011就是十进制的 9

1.2 以 0x 开头的整数位十六进制

  • 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F;
  • 0xF 就是十进制的 15
  • 0x11 就是十进制的 17
public class LiteralNumber {
    public static void main(String[] args) {
        int a = 05;
        int b = 011;
        int c = 0xF;
        int d = 0x11;  // x、X 都可以

        System.out.println(a);  // 5
        System.out.println(b);  // 9
        System.out.println(c);  // 15
        System.out.println(d);  // 17
    }
}

2. 按位运算符【每个二进制的位】

  • 按位并(AND):&
  • 按位或(OR):|
  • 按位异或(XOR):^【一句话,相异为真 ,运算规则是:两个数转为二进制,然后从高位开始比较,如果相同则为 0,不相同则为 1。】
  • 按位取反:~

储备知识:

  • int 有 4 个字节,每个字节有 8 位,一共 32 位。也就是这样的形式: 00000000 00000000 00000000 00000000;
  • 32 的二进制是:100000 ,把 32 的二进制放入上面储备知识中得出这样的效果:00000000 00000000 00000000 00100000。当然你也可以缩写成这样的效果:00100000。
  • 接下来我们可以进行取反,取反之后为的结果为: 11011111;
  • 操作的维度是 bit
public class BitCalc {
    public static void main(String[] args) {
        // F->15-> 1111
        // 二进制的 1111 1000
        int a = 0xF8;
        // 二进制的 1111 0100
        int b = 0xF4;
        // 二进制的 1111 1111
        int c = 0xFF;
        System.out.println(a & b); // 240
        System.out.println(a | b); // 252
        System.out.println(a ^ b); // 12
        System.out.println(~c); // -256
    }
}

/* 补充:
a	1111 1000
b	1111 0100
&	1111 0000
|	1111 1100
^	0000 1100
C	255 > 11111111
~	-255
*/

以我的工作经验来看,Java 中按位运算是比较少的。但是,我们要知道有这样一种操作。这样之后遇到,你就不会一脸懵!在这里,我不推荐你在日后的工作中有使用 **位 **运算符的倾向,当你想到,这个问题可以使用位运算符解决的时候,你再想想有没有更好的,更让人容易理解的方法。当然,如果真没有的话就算了。

3. 位移运算符

推荐先看里面部分内容:https://blog.csdn.net/qq_33254766/article/details/108702875open in new window

现代计算机是基于二进制的,我们就来看看,计算机语言中针对二进制的位操作。这里的位操作,也叫作位运算,就是直接对内存中的二进制位进行操作。常见的二进制位操作包括向左移位和向右移位的移位操作,以及“或”“与”“异或”的逻辑操作。「上面已经讲过与或非」下面我们来看位移运算符。

3.1 位移运算符

3.1.1 右移

移位的数字(x) >> 移位量(y)

右移运算是将移动的数字的 二进制位数 按指定 移位量 向右移动,右边低位溢出 y 位则舍弃。左边的空位一律补 0 或者补符号位,这由不同的机器而定。

若移位的数字不带符号位,则左边空位补入的数全部为 0;若是带符号数,则补入的数全部为原数最左边的符号位(正数 0,负数 1)

PS:

  • >>:符号位不动,其余位右移,符号位后边补 0,又称带符号右移「原本正数,那移动之后依然是正数。反之亦然。」
  • 当负数右移操作时,先对负数的原码求其补码再进行右移操作。

3.1.2 无符号右移

  • >>>:符号位一起右移,左边补 0,又称无符号右移 「无符号右移,那带着符号位意味着如果原本是正数,那符号位就是 0。右移之后,左边补 0。那还是正数。如果原本是负数,那无符号右移就会变成正数。」

3.1.3 左移

将移位的数字的 二进制位 全部左移指定的 移位量 移位量由右操作数指定,右操作数必须是非负值,其右边空出的位用 0 填补,高位左移溢出则舍弃该高位。

  • <<:左移,右边补 0。左移没有带符号位一说,因为符号位在最左侧。
    • 换一种方法理解:num << 1,左移1位相当于 num 乘以 2 的 1 次方
public class BitShift {
    public static void main(String[] args) {
        // 0x400 to binary 0100 0000 0000
        int a = 0x400;
        System.out.println(a);  // 1024
        System.out.println(a >> 1); // 0100 0000 0000 >> 1 -> 0010 0000 0000 to decimalism 512【1024/2】
        System.out.println(a >> 2); // 0100 0000 0000 >> 2 -> 0001 0000 0000 to decimalism 256【1024/4】

        System.out.println(a << 1); // 0100 0000 0000 << 1 -> 1000 0000 0000 to decimalism 2048【1024*2】
        System.out.println(a << 2); // 0100 0000 0000 << 2 -> 0001 0000 0000 0000 to decimalism 4096【1024*4】

        System.out.println(a >>> 1); // 0100 0000 0000 >> 1 -> 0010 0000 0000 to decimalism 512【1024/2】
        System.out.println(a >>> 2); // 0100 0000 0000 >> 2 -> 0001 0000 0000 to decimalism 256【1024/4】

        int b = -0x400;
        System.out.println(b);  // -1024
        System.out.println(b >> 1);
        /* -1024
         * 原码:1100 0000 0000
         * 反码:1011 1111 1111
         * 补码:1100 0000 0000
         * 右移:1010 0000 0000
         * 10 0000 0000 to decimalism 512 result >> -512
         */
        System.out.println(b >> 2);
        /* 补码:1100 0000 0000
         * 右移2:1001 0000 0000 to decimalism -256*/
        System.out.println(b << 1);
        /* 补码:0000 1100 0000 0000
         * 左移1:0001 1000 0000 0000 to decimalism -2048*/
        System.out.println(b << 2);
        /* 补码:0000 1100 0000 0000
         *  左移2:0011 0000 0000 0000 to decimalism -4096*/
        System.out.println(b >>> 1);  // 了解即可
        System.out.println(b >>> 2);


    }
}

3.2 位运算符不会改变原变量的值

3.2.1 按位运算符不会改变原本的变量的值

3.2.2 位移运算符不会改变原本的变量的值

public class BitOprtNotChangeVariableValue {
    public static void main(String[] args) {
        int a = 0x400;  // 0100 0000 0000 // 1024
        int b = 0xF4;
        int c = 0xFF;

        System.out.println(a >> 2);  // 256
        System.out.println(~a);  // -1025
        /* 原码:0100 0000 0000
        *  反码:0011 1111 1111
        *  补码:0100 0000 0000
        *  取反:1011 1111 1111 逐位取反,包括符位
        *  补码减1:1011 1111 1110
        *  再取反:1100 0000 0001 -> 取反后的二进制是负数 -> -1025
        */

        System.out.println(a | 0x8);
        /* a 原码:  0100 0000 0000
        *  0x8 原码:0000 0000 1000
        *           0100 0000 1000 -> 1032*/

        System.out.println(a);  // 1024
    }
}

3.3 位运算符用处

3.3.1 按位运算符

  • 掩码(MASK)

3.3.2 位移运算符

  • 高效除以 2
public class BitOprtUsage {
    public static void main(String[] args) {
        int base = 1;
        int is_student_mask = base;
        int is_programmer_mask = base << 1; // 0001 -> 0010
        int is_driver_mask = base << 2; // 0001 -> 0100
        int is_painter_mask = base << 3; // 0001 -> 1000

        int data = 5;

        boolean isStudent = (data & is_student_mask) != 0; // true
        //System.out.println(data & is_student_mask); // 1
        /*data:             0101
        * is_student_mask:  0001
        *                   0001 -> 1*/
        System.out.println(isStudent);

        boolean isProgrammer = (data & is_programmer_mask) != 0;
        System.out.println(isProgrammer);

        boolean isDriver = (data & is_driver_mask) != 0;
        System.out.println(isDriver);

        boolean isPainter = (data & is_painter_mask) != 0;
        System.out.println(isPainter);
    }
}

欢迎关注我公众号:AI悦创,有更多更好玩的等你发现!

公众号:AI悦创【二维码】

AI悦创·编程一对一

AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh

C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh

方法一:QQopen in new window

方法二:微信:Jiabcdefh

上次编辑于:
贡献者: AndersonHJB,AI悦创
你认为这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度