位运算,原码、反码、补码一网打尽

十进制、二进制、十六进制、反码、源码、补码、>>>为逻辑移位符,>> 算数移位符,<< 移位符

正数的反码、源码、补码是一样的,负数的补码等于负数的反码+1

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

    例如:假设计算机字长为8位,十进制中的数+3 ,转换成二进制就是 0000 0011。如果是-3 ,就是 1000 0011 。这里的 0000 0011 和 1000 0011 就是               机器数。

真值:因为第一位是符号位,所以机器数的形式值就不等于真正的数值。

    例如上面的有符号数 1000 0011,其最高位1代表负,其真正的数值是 -3,而不是形式值131(1000 0011 转换成十进制等于131)。

    所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。
    例:0000 0001 的真值 = +000 0001 = +1

      1000 0001 的真值 = –000 0001 = –1

原码:原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。因为第一位是符号位, 所以8位二进制数的取值范围就是:[1111 1111 , 0111 1111]
即[-127 , 127] (这和我们已知的[-128,127]不一样。假设计算机字长是8位的二进制:

    正数:[+1]原 = 0000 0001原

    负数:[-1]原 = 1000 0001原

反码:反码的表现方式,正数的反码是他本身,负数的反码在其原码的基础上,符号位不变,其他位按位取反。

    例: [+1] 原码=0000 0001 反码= 0000 0001

    例:[-1]原码=1000 0001 反码= 0111 1110  

补码:补码的表现方式,正数的补码是他本身,负数的补码是在原码的基础上,符号位不变,其他位按位取反,并+1.

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

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

低字长转为高字长,补码左侧补符号位到满足高字长的位数。

    例:[+2] 原码 0000 0010 反码=0000 0010 8位补码=0000 0010 16位补码 = 0000 0000 0000 0010

    例:[-2] 原码 1000 0010 反码=1111 1101 8位补码=1111 1110 16位补码= 1111 1111 1111 1110

位运算(负数的运算是以补码的方式计算的,如果运算结果首位为1,结果也需要求一次补码):

  位运算规则:

    Java数值运算过程中都是先将十进制转换为二进制然后再进行运算,再把二进制数据转换为十进制展现给用户。二进制运算规则如下:

    1、对于有符号的而言,最高位为符号位,0表示正数,1表示负数

    2、正数的原码,反码和补码都一样,三码合一

    3、负数的反码:符号位保持不限,其他位取反

    4、负数的补码:反码 + 1

    5、0的反码和补码都是0

    6、计算机的运算的时候,都是将原码转成补码进行运算的

    7、我们看运算结果要看原码。

  与运算(&):两个数相同位置的比特位进行与运算,若两个比特位均为1,则结果就为1,否则为0。

    例:5 & 7 = 0000 0101 & 0000 0111 = 0000 0101 = 5

    例:5 & -7 = 0000 0101 & 1000 0111的补码(1111 1001)= 0000 0001 反码 = 0000 0001 原码 = 1

  或运算(|):两个数相同位置的比特位进行与运算,若两个比特位均为0,则结果就为0,否则为1。

    例:5 | 7 =  0000 0101 | 0000 0111 = 0000 0111 = 7

    例:5 | -7 = 0000 0101 | 1000 0111的补码(1111 1001)= 1111 1101(运算结果) = 1111 1100 (运算结果的反码)= 1000 0011 (运算结果原码) = -3

   异或运算(^):两个数相同位置的比特位进行与运算,若两个比特位相同,则为0,若不相同,则为1。

    例:5 ^ 7 =  0000 0101 ^ 0000 0111 = 0000 0010 = 2

    例:5 ^ -7 =  0000 0101 ^ 1000 0111的补码(1111 1001)= 1111 1100(运算结果) = 1111 1011 (运算结果反码)= 1000 0100(运算结果原码) = -4

   取反运算(~):将数的比特位取反。

    例:~5 = 0000 0101 (补码) = 1111 1010 (运算结果)= 1111 1001 (运算结果反码) = 1000 0110 (运算结果原码) = -6

  左移运算(<<):将一个数表示的二进制向左移n位,符号位和其他位一样要移动,移出的部分将被抛弃,右侧低位补0,符号位可能会发生变化(因为符号位被会移出抛弃,新的符号位由右侧的左移替上)。

    例:15 << 3 = 0000 1111 << 3 = 0111 1000(运算结果) = 0111 1000(运算结果原码正数三码合一) = 8 + 16 +32 + 64 = 120

    例:15 << 30 = 0000 0000 0000 0000 0000 0000 0000 1111 << 30 = 1100 0000 0000 0000 0000 0000 0000 0000(运算结果) = 1011 1111 1111 1111 1111 1111 1111 1111(运算结果反码)=1100 0000 0000 0000 0000 0000 0000 0000(运算结果原码)= -2的30次方

    例:-15 << 3 = 1000 1111(原码) << 3 =  1111 0001(补码) << 3 = 111 1000 1000(运算结果) = 111 1000 0111(运算结果反码)= 100 0111 1000(运算结果原码)= -(8+16+32+64)= -120

  右移运算(>>):将一个数表示的二进制向右移n位,移出的部分将被抛弃,左侧高位补符号位。例如正数左侧补0,负数左侧补1。

    例:15 >> 1 = 0000 1111 >> 1 = 0000 0111 = 7

    例:-15 >> 1 = 1000 1111(原码) >> 1 = 1111 0001(补码) >> 1 = 1111 1000(运算结果) = 1111 0111(运算结果反码) =1000 1000(运算结果原码)= -8

     无符号右移运算(>>>):将一个数表示的二进制无符号向右移n位,移出的部分将被抛弃,无论是正数,还是负数,左侧高位都补0。

    例:15 >>> 1 = 0000 1111 >>> 1 = 0000 0111 = 7

    例:-15 >>> 1 = 1000 0000 0000 0000 0000 0000 0000 1111 >>> 1 = 1111 1111 1111 1111 1111 1111 1111 0001(补码) >>> 1 = 0111 1111 1111 1111 1111 1111 1111 1000 = 2147483640

posted @ 2022-11-28 17:13  低调小雄  阅读(412)  评论(0编辑  收藏  举报