原码、 反码、 补码、位运算符

一 概念

原码、反码和补码是计算机中用于表示有符号整数的三种不同的编码方式。

原码(Sign-Magnitude):
  • 原码是最简单直观的表示方法,最高位表示符号位,0代表正数,1代表负数,其余位表示数值部分。
  • 例如,正数+5的原码为0000 0101,负数-5的原码为1000 0101。
反码(One’s Complement):
  • 反码的表示方法是对于正数与原码相同,对于负数则是在原码的基础上,符号位不变,其他位取反(0变为1,1变为0)。
  • 例如,正数+5的反码为0000 0101,负数-5的反码为1111 1010。
补码(Two’s Complement):
  • 补码是计算机中最常用的表示有符号整数的方法,对于正数与原码、反码相同,对于负数,其补码是其反码加1。
  • 例如,正数+5的补码为0000 0101,负数-5的补码为1111 1011。

补码表示方法具有以下优势:

  • 能够实现加减法的统一处理,无需单独设计减法电路。
  • 避免了0的两个表示(正零和负零),简化了运算规则。
  • 在计算机硬件中,使用补码可以简化逻辑电路的设计。

总体来说,原码、反码和补码是用来表示有符号整数的不同编码方式,而补码在计算机中得到了广泛的应用。

特点总结
  1. 二进制的最高位是符号位:0 是正数,1是负数
  2. 正数的 原码、反码、补码 是一样的
  3. 负数的反码 = 原码符号位不变,其它位取反(0->1 ; 1->0)
  4. 负数的补码 = 负数的反码 + 1 ,负数的反码 = 负数的补码 - 1
  5. 0 的反码,补码都是0
  6. 在计算机运算的时候,都是以 补码的方式来运算
  7. 当看运算结果的时候,要看 原码

二 位运算符

java 中有 7 个位运算&、 |、 ^、 ~、 >>、 <<和 >>>
分别是 按位与& 按位或| 按位异或^ 按位取反~ 右移运算符>> 左移运算符<< 无符号右移运算符>>>

运算规则如下:

  • 按位与&:将两个操作数的每个位进行与运算,如果两个对应位都为1,则结果为1,否则为0。
int a = 5;    // 二进制表示为 0000 0101
int b = 3;    // 二进制表示为 0000 0011
int result = a & b;  // 结果为 0000 0001,即1
  • 按位或| :将两个操作数的每个位进行或运算,如果两个对应位中有一个为1,则结果为1,否则为0。
int a = 5;    // 二进制表示为 0000 0101
int b = 3;    // 二进制表示为 0000 0011
int result = a | b;  // 结果为 0000 0111,即7
  • 按位异或^ :将两个操作数的每个位进行异或运算,如果两个对应位不同,则结果为1,否则为0。
int a = 5;    // 二进制表示为 0000 0101
int b = 3;    // 二进制表示为 0000 0011
int result = a ^ b;  // 结果为 0000 0110,即6
  • 按位取反~ 对操作数的每个位进行取反操作,即0变为1,1变为0。
int a = 5;    // 二进制表示为 0000 0101
int result = ~a;  // 结果为 1111 1010,即-6
  • 右移运算符 >>:将操作数的所有位向右移动指定的位数,移出的位被丢弃,左边用符号位填充(对于正数则用0填充)。
  • 本质 20 / 2 / 2 = 5 原本的数 / 2^位移数
int a = 20;    // 二进制表示为 0001 0100
int result = a >> 2;  // 结果为 0000 0101,即5 
  • 左移运算符 <<:将操作数的所有位向左移动指定的位数,右边用0填充。
  • 本质 5 * 2 * 2 * 2 = 20 原本的数 * 2^位移数
int a = 5;    // 二进制表示为 0000 0101
int result = a << 3;  // 结果为 0010 1000,即40
  • 无符号右移运算符 >>>:将操作数的所有位向右移动指定的位数,移出的位被丢弃,左边用0填充。
int a = -20;    // 二进制表示为 1111 1111 1111 1111 1111 1111 1110 1100
int result = a >>> 2;  // 结果为 0011 1111 1111 1111 1111 1111 1111 0110,即1073741814

三 代码演示

例子:计算 2&3 ~-2 ~2 2|3 2^3 的结果

public static void main (String[] args) {
        System.out.print("================ 2&3:");
        // 推导
        // 1. 取 2 的原码: 00000000 00000000 00000000 00000010
        // 2. 取 2 的反码: 00000000 00000000 00000000 00000010
        // 3. 取 2 的补码: 00000000 00000000 00000000 00000010
        // 4. 取 3 的原码: 00000000 00000000 00000000 00000011
        // 5. 取 3 的反码: 00000000 00000000 00000000 00000011
        // 6. 取 3 的补码: 00000000 00000000 00000000 00000011
        // 7. 运算后的补码:00000000 00000000 00000000 00000010
        // 8. 运算后的反码/原码/补码是一致的
        System.out.println(2&3); // 2


        System.out.print("================ ~-2:");
        // 推导
        // 1. 取 -2 的原码: 10000000 00000000 00000000 00000010
        // 2. 取 -2 的反码: 11111111 11111111 11111111 11111101
        // 3. 取 -2 的补码: 11111111 11111111 11111111 11111110
        // 4. 运算后的补码:  00000000 00000000 00000000 00000001
        // 5. 运算后的反码/原码/补码是一致的
        System.out.println(~-2); //1

        System.out.print("================ ~2:");
        // 推导
        // 1. 取 2 的原码: 00000000 00000000 00000000 00000010
        // 2. 取 2 的反码: 00000000 00000000 00000000 00000010
        // 3. 取 2 的补码: 00000000 00000000 00000000 00000010
        // 4. 运算后的补码: 11111111 11111111 11111111 11111101
        // 5. 运算后的反码: 11111111 11111111 11111111 11111100
        // 6. 运算后的原码: 10000000 00000000 00000000 00000011
        System.out.println(~2); // -3


        System.out.print("================ 2|3:");
        // 推导
        // 1. 取 2 的原码: 00000000 00000000 00000000 00000010
        // 2. 取 2 的反码: 00000000 00000000 00000000 00000010
        // 3. 取 2 的补码: 00000000 00000000 00000000 00000011
        // 4. 取 3 的原码: 00000000 00000000 00000000 00000011
        // 5. 取 3 的反码: 00000000 00000000 00000000 00000011
        // 6. 取 3 的补码: 00000000 00000000 00000000 00000011
        // 7. 运算后的补码: 00000000 00000000 00000000 00000011
        // 8. 运算后的反码/原码/补码是一致的
        System.out.println(2|3); //3

        System.out.print("================ 2^3:");
        // 推导
        // 1. 取 2 的原码: 00000000 00000000 00000000 00000010
        // 2. 取 2 的反码: 00000000 00000000 00000000 00000010
        // 3. 取 2 的补码: 00000000 00000000 00000000 00000010
        // 4. 取 3 的原码: 00000000 00000000 00000000 00000011
        // 5. 取 3 的反码: 00000000 00000000 00000000 00000011
        // 6. 取 3 的补码: 00000000 00000000 00000000 00000011
        // 7. 运算后的补码: 00000000 00000000 00000000 00000001
        // 8. 运算后的反码/原码/补码是一致的
        System.out.println(2^3); // 1
}

计算 1 >> 2 -1 >>2 1 << 2 -1 << 2 3 >>> 2

public static void main (String[] args) {
		int a = 1 >> 2; // 0
        // 推导
        // 1. 取 1 的原码: 00000000 00000000 00000000 00000001
        // 2. 1的反码补码一致: 00000000 00000000 00000000 00000001
        // 3. 1 右移 2 位: 00000000 00000000 00000000 00000000
        // 4.00000000 00000000 00000000 00000000 转成十进制为 0
		System.out.println("a = " + a);
		
		int b = -1 >> 2; // -1
        // 推导
        // 1. 取 -1 的原码: 10000000 00000000 00000000 00000001
        // 2. 取 -1 的反码: 11111111 11111111 11111111 11111110
        // 3. 取 -1 的补码: 11111111 11111111 11111111 11111111
        // 4. -1 右移 2 位: 11111111 11111111 11111111 11111111
        // 5. 补码转反码:    11111111 11111111 11111111 11111110
        // 6. 反码转原码:    10000000 00000000 00000000 00000001
        // 7. 结果为 -1
        System.out.println("b = " + b);

		int c = 1 << 2; // 4
        // 推导
        // 1. 取 1 的原码: 00000000 00000000 00000000 00000001
        // 2. 1的反码补码一致: 00000000 00000000 00000000 00000001
        // 3. 1 左移 2 位: 00000000 00000000 00000000 00000100
        // 4.00000000 00000000 00000000 00000100 转成十进制为 4
        System.out.println("c = " + c);
		
		int d = -1 << 2; // -4
        // 推导
        // 1. 取 -1 的原码: 10000000 00000000 00000000 00000001
        // 2. 取 -1 的反码: 11111111 11111111 11111111 11111110
        // 3. 取 -1 的补码: 11111111 11111111 11111111 11111111
        // 4. -1 左移 2 位: 11111111 11111111 11111111 11111100
        // 5. 补码转反码:    11111111 11111111 11111111 11111011
        // 6. 反码转原码:    10000000 00000000 00000000 00000100
        // 7. 结果为 -4
        System.out.println("d = " + d);

		int e = 3 >>> 2;
        // 推导
        // 1. 取 3 的原码: 00000000 00000000 00000000 00000011
        // 2. 3的反码补码一致: 00000000 00000000 00000000 00000011
        // 3. 3 无符号右移 2 位: 00000000 00000000 00000000 00000000
        // 4.00000000 00000000 00000000 00000000 转成十进制为 0
        System.out.println("e = " + e);

}
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值