Title

原码反码补码及简单应用

0 前提

在Java中,所有数据的表示方式都是以补码形式来表示

在Java中,所有数据的表示方式都是以补码形式来表示

在Java中,所有数据的表示方式都是以补码形式来表示

    public static void main(String[] args) {
        int num = 5;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
        num = -1;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
        num = -3;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
    }
# 5的补码 101   								#int是32位长度  但是前面都是0 省略了
# -1的补码 11111111111111111111111111111111
# -3的补码 11111111111111111111111111111101

0.1 机器数

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数0,负数为1

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是0000 0011。如果是 -3 ,就是 1111 1101 。那么,这里的 00000011 和 1111 1101 就是机器数。 机器数包含了符号和数值部分。

0.2 真值

因为第一位是符号位,所以机器数的形式值就不能很好的表示真正的数值。

例如上面的有符号数1111 1101(8位),其最高位1代表负,其真正数值是 -3 而不是形式值253(1111 1101按无符号整数转换成十进制等于253)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –0111 1111 = –127;这里所说的比如-3二进制代码为10000011,就是我们计算机里面对-3表示的原码

1 规定

1.1 原码

原码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.

比如如果是8位二进制

[+1]原 = 0000 0001

[-1]原 = 1000 0001

[-3]原 = 1000 0011

比如如果是32位二进制

[+1]原 = 0000 0000 0000 0000 0000 0000 0000 0001

[-3]原 = 1000 0000 0000 0000 0000 0000 0000 0011

1.2 反码

反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外

8位二进制

[+1] = [ 0000 0001 ]原码 = [ 0000 0001 ]反码;

[-1] = [ 1000 0001 ]原码 = [ 1111 1110 ]反码;

1.3 补码

补码:正数的补码为其本身,负数的补码为其反码再加1

8位二进制

[+1]=[0000 0001]原码=[0000 0001]反码=[0000 0001]补码

[-1] =[1000 0001]原码=[1111 1110]反码=[1111 1111]补码

补码的补码为原码

2 总结

  • 在Java中,所有数据的表示方式都是以补码形式来表示

  • 正数:原码、反码、补码相同

  • 负数:符号位(最高位)为1,其余各位是对原码取反是反码,然后反码加1是补码

3 二进制运算

  • 与 (&)按位与运算
  • 或 (|)按位或运算
  • 异或 (^)异或运算
  • 非(~)运算符

3.1 测试1

    public static void main(String[] args) {
        int num = ~5;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
    }
#-6的补码 11111111111111111111111111111010 

解释

5非运算为什么是-6?

  • 5对应补码 0000 0101;

  • 5取非(所有二进制位上取非):1111 1010

  • 求补码1111 1010的原码,由补码的补码就是原码知:

    [1111 1010] -> 反码 [1000 0101] ->补码 [1000 0110]

    则 补码1111 1010的原码为1000 0110。

    原码为1000 0110对应的真值为最高位1为负数,各级求和-1*(4*1 + 2*1)= -6

注意,取非和取反码不一样

  • 取非是所有位上都取反;

  • 取反码,最高位即符号位不取反,其他位取反

3.2 测试2

位移运算:

  • >> n 右移n位,一个正数的补码整体右移n位,不足补0,负数最高位补1
  • << m 左移m位,一个数的补码整体左移m位,不足补0
    public static void main(String[] args) {
        int num = 5 << 2;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
        num = 5 >> 5;
        System.out.println(num + "的补码 " + Integer.toBinaryString(num));
    }
# 20的补码 10100
# 0的补码 0

解释

左移:

  • 5的补码 0000 0101;
  • 先左移两位后:0001 0100;(二进制补码整体左移两位,末位空出的补上0)
  • 0001 0100计算后1*(16 + 4)= 20;

右移:

  • 5的补码 0000 0101;
  • 先右移五位后:0000 0000;
  • 对应0

注意:

  • 负数的位移运算要小心,负数右移最高位补的是1,而不是0了

3.3 应用

3.3.1 快速计算奇数还是偶数

    public static void main(String[] args) {
       int num = -150;
       if((num & 1) == 0){
           System.out.println("偶数");
       }else {
           System.out.println("奇数");
       }
    }

3.3.2 快速计算2^n(2的n次方)

    public static void main(String[] args) {
        System.out.println(1 << 16);
    }

注意:整数默认是int,而int是32位有符号整数,取值范围-2^31 到(2^31 -1)

所以一个数的左移不要超过范围了。

posted @ 2021-09-09 00:09  apeGcWell  阅读(229)  评论(0编辑  收藏  举报