Java 原码、反码、补码 & 位运算

本文详细介绍了原码、反码、补码的概念及其在计算机中的应用,以及位运算符如与(&amp;),或(|),非(~),异或(^),左移(<<)和右移(>>,>>>)的操作原理和区别。通过示例展示了有符号和无符号右移在整数处理中的表现。
摘要由CSDN通过智能技术生成

1. 原码、反码、补码

1.1 原码

就是二进制定点表示法,即最高位为符号位:“0”表示正,“1”表示负,其余位表示数值的大小。
该数字不进行其他操作时数字最原始的二进制表示, 对于原码来说,绝对值相等的正数和负数只有符号位不同。

1.2 反码

正数的反码与其原码相同;
负数的反码是对其原码逐位取反,但符号位除外。(只需要将原码除符号位以外的位数取反,即0改为1,1改为0)

1.3 补码

正数的补码与其原码相同;
负数的补码是在其反码的末位加1;
现在的计算机都用补码存储整形数值。

计算机为什么有反码和补码?
有人会有疑惑为什么要用反码,补码,不直接用原码呢?
先搞清楚一点反码、补码、原码是针对二进制数而言,计算机若用原码相加减,正数加正数不会出错,然而正数和负数原码相加就会出错。说白了,补码、反码就是为了简化减法而来的,将减号化为负数后再将负数化为补码求加法,就跟正数没关系了!
不管是正整数还是正小数,原码,反码,补码都全部相同。计算机中所有数都是以补码形式存储的。
1.10+(1)时:1010 + 0001 = 1011,即11。
2.10+(-1)时:00001010 + 10000001 = 10001011 ,即 -11 (原码参与加法运算)
3.10+(-1)时:00001010 + 11111111 = 00001001,即 9 (补码参与加法运算)

1.4 byte的最大值

八位二进制中正数最大是0111 1111(第一位是符号位),所以byte正数范围是(0-127),共有2^7=128个数值;

1.5 byte的最小值

八位二进制中负数计算需要用反码末位+1得到补码,所以1111 1111补码就是1000 0001=-1,一直到1000 0001补码是1111 1111= -127,而1000 0000的补码是1000 0000也就是-0,没有意义,此处计算机将它计为-128,故一个字节的取值范围是[-128,127]。

2. 位运算

2.1 & 与

两个位都为1时,结果才为1

2.2 | 或

两个位都为0时,结果才为0;
或者表述为,有一个是1,结果就是1,否则是0。

2.3 ~ 非

0变1,1变0

2.4 ^ 异或

相同为0,不同为1

2.5 << 左移 (没有无符号左移)

符号位不变,正数负数都是低位用0补齐,不管对于正数还是负数,都相当于乘以2^n

2.6 >> 右移 (有符号右移)

高位用符号位补齐(高位正数用用0补,负数用1补)

2.7 >>> 无符号右移

正数负数高位都用0补(由于符号位被拱占,导致负数变成正数)

2.8 有符号右移和无符号右移的区别

测试代码

public class BitArithmetic {
    public static void main(String[] args) {
        // 下面展示有符号右移和无符号右移的区别

		// 有符号右移( >> )
        int i1 = 128;
        int r1 = i1 >> 1;
        int r11 = i1 >> 2;

        int i2 = -128;
        int r2 = i2 >> 1;
        int r22 = i2 >> 2;


        // 无符号右移( >>> )
        int i3 = 128;
        int r3 = i3 >>> 1;
        int r33 = i3 >>> 2;

        int i4 = -128;
        int r4 = i4 >>> 1;
        int r44 = i4 >>> 2;

        // 打印结果
        print(i1, 1, r1, ">>");
        print(i1, 2, r11, ">>");
        print(i2, 1, r2, ">>");
        print(i2, 2, r22, ">>");
        print(i3, 1, r3, ">>>");
        print(i3, 2, r33, ">>>");
        print(i4, 1, r4, ">>>");
        print(i4, 2, r44, ">>>");
        print(Integer.MAX_VALUE, 1, r44, ">>");
        print(Integer.MAX_VALUE, 1, r44, ">>>");
        print(Integer.MIN_VALUE, 1, r44, ">>");
        print(Integer.MIN_VALUE, 1, r44, ">>>");
    }

    private static void print(int i, int y, int r, String operator) {

        System.out.println(i + " " + operator + " " + y + " = " + r);
        System.out.println("二进制表示: " + getIntBits(i) + " " + operator + " " + y + " = " + getIntBits(r));
        System.out.println("====================");
    }

	private static String getIntBits(int num) {
	    String str = "";
	    for (int i = 31; i >= 0; i--) {
	        str = str + ((num & (1 << i)) == 0 ? "0" : "1");
	    }
	
	    return str;
	}
}

打印结果

128 >> 1 = 64
二进制表示: 00000000000000000000000010000000 >> 1 = 00000000000000000000000001000000
====================
128 >> 2 = 32
二进制表示: 00000000000000000000000010000000 >> 2 = 00000000000000000000000000100000
====================
-128 >> 1 = -64
二进制表示: 11111111111111111111111110000000 >> 1 = 11111111111111111111111111000000
====================
-128 >> 2 = -32
二进制表示: 11111111111111111111111110000000 >> 2 = 11111111111111111111111111100000
====================
128 >>> 1 = 64
二进制表示: 00000000000000000000000010000000 >>> 1 = 00000000000000000000000001000000
====================
128 >>> 2 = 32
二进制表示: 00000000000000000000000010000000 >>> 2 = 00000000000000000000000000100000
====================
-128 >>> 1 = 2147483584
二进制表示: 11111111111111111111111110000000 >>> 1 = 01111111111111111111111111000000
====================
-128 >>> 2 = 1073741792
二进制表示: 11111111111111111111111110000000 >>> 2 = 00111111111111111111111111100000
====================
2147483647 >> 1 = 1073741792
二进制表示: 01111111111111111111111111111111 >> 1 = 00111111111111111111111111100000
====================
2147483647 >>> 1 = 1073741792
二进制表示: 01111111111111111111111111111111 >>> 1 = 00111111111111111111111111100000
====================
-2147483648 >> 1 = 1073741792
二进制表示: 10000000000000000000000000000000 >> 1 = 00111111111111111111111111100000
====================
-2147483648 >>> 1 = 1073741792
二进制表示: 10000000000000000000000000000000 >>> 1 = 00111111111111111111111111100000
====================

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值