【一篇文章带你搞懂补码原理】计算机底层原理:补码的详细介绍和解释、补码的溢出处理,Java中位运算操作的底层逻辑和规则。

一、补码

       补码:是一种在计算机中表示有符号整数的方法。在计算机系统中,数值一律用补码来表示和存储。
       补码的最高位(最左边的位)用作符号位,0表示正数,1表示负数。
             如:int类型的补码,共32(从第0位到第31)。最左边一位(31)是符号位,其余31位是数值存储位(全是01)。
             在补码运算中,无论正数还是负数,符号位都会参与运算。这是补码表示法的核心特性之一,也是其硬件实现简单高效的关键原因。
       正数的补码:等于其二进制表示本身(也叫原码),就是整数的二进制是多少,它的补码也是多少。
       负数的补码:通过将其对应正数的补码(原码)表示按位取反,然后再加1得到负数的补码。负数补码 = 反码(正数补码按位取反) + 1。

       如下,计算机对于int类型 -5 取补码的过程:

        1.先取5的原码(5的二进制):
          00000000 00000000 00000000 00000101
        2.对原码按位取反(得到反码):
     ^5 : 11111111 11111111 11111111 11111010
        3.反码 + 1 = 补码
          11111111 11111111 11111111 11111010
     +1 : 00000000 00000000 00000000 00000001
   --------------------------------------------
     -5 : 11111111 11111111 11111111 11111011
        最后得到-5的补码:11111111 11111111 11111111 11111011 (-5 的存储形式)

        0 的补码全是0-1的补码全是1。
        在Java中,整数的加减法运算完全基于补码,计算机硬件直接对补码进行二进制计算。
     

     补码加减法的核心规则:
       加法:直接按位相加,超出位数的高位丢弃。
       减法:转换为加法。如:A - B = A + (-B)【减法转换为加法是由硬件去做的】

       以下以 5 + (-3) 示例,等价于5 - 3(减法)
    5: 00000000 00000000 00000000 00000101
   -3: 11111111 11111111 11111111 11111101
   ----------------------------------------
       00000000 00000000 00000000 00000010
       得到的补码就是2的补码。结果正确。
       下面详细讲解 5 + (-3) 补码的运算过程:
             5-3的最低位(从右向左,第0)都为1。位运算规则:1 + 1 = 10,当前(0)0,向高一位进1。
             因此第一位是:0 + 0 + (进位)1 = 1。第二位都是1。因此结果为:1 + 1 = 0(当前位) + 1(进位)。
             后面从第3位起到第31(最高位)都是 0(5产生的) + 1(3的产生的) + 1(进位) = 0(当前位) + 1(进位)。
             因此不断的向高位进1,然后自身位为0。所以产生的结果的高位全是0。对于最高位第31位自身为0,但进1的问题。
             (31位产生的进位1)它会被CPU的硬件电路自动丢弃,因为超出了int32位存储范围(因为寄存器只有32)。
       以下是详细的运算拆解,方便大家直观理解:
        位序	    5的位  -3的位  进位输入	 结果位   进位输出	计算逻辑
      --------------------------------------------------------------------------------
        0(0)	  1	      1	       0	   0	      1	     1 + 1 + 0 = 10 (01)
        1	          0	      0	       1	   1	      0	     0 + 0 + 1 = 01 (10)
        2	          1	      1	       0	   0	      1	     1 + 1 + 0 = 10 (01)
        3~30	      0	      1	       1	   0	      1	     0 + 1 + 1 = 10 (01)
        31(符号位)	  0	      1	       1	   0	      1	     0 + 1 + 1 = 10 (01)
      ---------------------------------------------------------------------------------

二、溢出处理

       溢出处理:整数溢出在补码体系下类似于"环绕"(循环)。
       补码溢出"环绕"原理:int类型为例:

       int的范围:最小值,Integer.MIN_VALUE = -2147483648; 最大值,Integer.MAX_VALUE = 2147483647;
       溢出后:

             上溢(Overflow):超过 MAX_VALUE ——> 跳转到 MIN_VALUE 继续增加。
             如:
             int a = Integer.MAX_VALUE;
             a = a + 1;
             System.out.println(a);  // 输出:-2147483648 (MIN_VALUE)
             二进制解释:
             MAX_VALUE:  01111111 11111111 11111111 11111111
             +1:         00000000 00000000 00000000 00000001
             -----------------------------------------------
             Result:     10000000 00000000 00000000 00000000 (MIN_VALUE)

======================================================================================

             下溢(Underflow):低于 MIN_VALUE ——> 跳转到 MAX_VALUE 继续减少。
             如:
             int b = Integer.MIN_VALUE;
             b = b - 1;
             System.out.println(b);  // 输出:2147483647 (MAX_VALUE)
             二进制解释:
             MIN_VALUE:  10000000 00000000 00000000 00000000
             +(-1):      11111111 11111111 11111111 11111111
             -----------------------------------------------
             Result:     01111111 11111111 11111111 11111111 (MAX_VALUE)  【提示:最高位的进位1直接被丢弃】

        补码运算有着数学封闭性,这是计算机底层采取补码的重要原因之一。
        Java遵循补码规则,明确允许溢出静默环绕。

三、Java移位运算

       Java位运算( <<>>>>> )的补码深度解析:
       左移( << ):
           规则:所有位向左移动,低位补 0 ,高位直接丢弃(包括符号位)。
           数学意义:等价于乘以(2的位移数的次方)。【可能溢出】
           示例: -5 << 2
      -5 : 11111111 11111111 11111111 11111011
           左移2位后的补码:
           11111111 11111111 11111111 11101100
           结果就是: -20 (-5 * 4)
           【如果想要求证也很简单:负数补码 = 反码(正数补码取反) + 1。那么:(负数补码 - 1)取反就等于对应正数的补码】
           如下:
     -20 : 11111111 11111111 11111111 11101100
   +(-1) : 11111111 11111111 11111111 11111111
   -------------------------------------------
           11111111 11111111 11111111 11101011
  ^(取反) : 00000000 00000000 00000000 00010100  = 20
  ---------------------------------------------------
           注意点:符号位可能被覆盖,若左移后符号位从 10,负数会变正数(溢出)。
           如: -1 << 31 = -2147483648(Int_MIN_VALUE)Java位移操作规定:Java对位移操作的处理有一个关键规则:位移(即移动的位数)会先进行模运算。
           Java规范规定:对于int类型的位移操作( <<>>>>>)实际的位移数是 n % 32。
           如: -1 << 32 = -1(实际未移动)。【32 % 32 = 01 << 35 == 1 << 3。【35 % 32 = 3】
           避免无意义的超范围位移,保持运算效率。
       右移( >> ):
           规则:所有位向右移动,高位补符号位(正数补0,负数补1)。
           数学意义:等价于除以2^n并向负无穷取整(对负数友好)。
           示例: -20 >> 2
     -20 : 11111111 11111111 11111111 11101100
-20 >> 2 : 11111111 11111111 11111111 11111011 = -5
           【注意点:负数右移结果比除法更小】
           如:System.out.println(-15 >> 2); // 输出: -4 (-15/4=-3.75,向负无穷取整)

       无符号右移( >>> ):
           规则:所有位向右移动,高位强制补0(无论正负)
           数学意义:逻辑右移,无符号除法(负数会变正数)
           示例: -20 >>> 2
     -20 : 11111111 11111111 11111111 11101100
-20 >>>2 : 00111111 11111111 11111111 11111011 = 1073741819
           用途:处理无符号数据(如哈希算法、读取网络协议的字段)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值