网站Logo 苏叶的belog

源码反码补码和位运算

wdadwa
4
2026-03-09

原码

原码是最直观的二进制表示法:

  • 符号位:最高位表示符号(0为正,1为负)。
  • 数值位:剩余位表示绝对值。
  • 例如:
    • +50 0101(假设为5位二进制)
    • -51 0101

原码的运算缺陷

  • 加减法需要区分符号
    • 同号相加:直接相加,符号不变。
    • 异号相加:需转换为减法,可能导致结果符号错误。
  • 符号位参与运算
    • 原码的符号位和数值位需分开处理,导致硬件电路复杂。
    • 示例:计算 1 - 1(即 1 + (-1)):
      • 原码形式:0 0001(+1) + 1 0001(-1)
      • 直接相加:符号位参与运算 → 1 0010(-2),显然错误

反码

为了解决原码不能计算负数的问题出现的

计算规则:正数的反码不变,负数的反码在原码的基础上,符号位不变数值取反,0 变 1,1 变 0

反码的弊端:

十进制数原码反码
+10000 00010000 0001
+00000 00000000 0000
-01000 00001111 1111
-11000 00011111 1110

缺陷:反码出现从负数计算结果到正数这种跨 0 的情况,因为反码存在 -0 和 +0 故最终结果与真实结果会有 1 个误差

补码

为了解决反码跨 0 计算出现误差 1 的情况出现的

计算规则:正数补码不变,负数补码是在反码的基础上 +1

十进制数原码反码补码
00000 00000000 00000000 0000
-11000 00011111 11101111 1111
-21000 00101111 11011111 1110

计算机中存储的数据都是以补码形式存储的哦!这就解释了为什么 byte 的数据类型是 -127 到 +128 了

类型转换原理

隐式类型转换:核心就是前面补 0

public class Test{
    public static void main(String[] args){
        byte a=10;//0000 1010
        int b=a;//在a前面补上3个字节的0即3*8=24个0	0000 0000 0000 0000 0000 0000 0000 1010
    }
}

强制类型转换:

public class Test{
    public static void main(String[] args){
        int a=300;//0000 0000 0000 0000 0000 0001 0010 1100
        byte b=(byte)a;//将前面3个字节3*24个0去掉,0010 1100
        //因为是去掉前面的0这就解释了为什么强制类型转换会导致数据丢失了!
    }
}

位运算

  • &,逻辑与:0 为 false,1 为 true,如果都是 true 结果才为 true 否则都为 false

    举例:

    int a=200
    int b=10
    int sum=a&b
    变为补码形式
    a:	 0000 0000 0000 0000 0000 0000 1100 1000
    b:	 0000 0000 0000 0000 0000 0000 0000 1010
    &---------------------------------------------
    sum:0000 0000 0000 0000 0000 0000 0000 1000
    再转换为十进制sum=8
    
  • | 逻辑或:0 为 false,1 为 true,只要有 true 结果就是 true

    举例

    int a=200
    int b=10
    int sum=a|b
    变为补码形式
    a:	 0000 0000 0000 0000 0000 0000 1100 1000
    b:	 0000 0000 0000 0000 0000 0000 0000 1010
    |---------------------------------------------
    sum:0000 0000 0000 0000 0000 0000 1100 1010
    再转换为十进制sum=202
    
  • <<左移:把二进制向左移动,低位补 0

    举例

    a=200
    a:	 0000 0000 0000 0000 0000 0000 1100 1000
    a<<2	将a的二进制向左移2bit
    00 0000 0000 0000 0000 0000 1100 100000
    此时变为800
    记住左移一次就是乘2
    
  • >>右移:把二进制向右移动,高位补 0 或 1

    举例

    a=200
    a:	 0000 0000 0000 0000 0000 0000 1100 1000
    a>>2 将a的二进制向右移动2bit
    000000 0000 0000 0000 0000 0000 1100 10
    符号位根据原来是正数还是负数进行补
    原来是正数补0,负数补1
    并且右移一次除2
    
  • 无符号右移>>>

    向右移动,高位补 0

动物装饰