原码,补码,反码和常见二进制位运算

原码,补码,反码

  • 原码
    用最高位的二进制位表示符号。0 = 正数,1 = 负数。
    正数的原码就是其二进制位本身。
    负数的源码是对应绝对值的二进制位,但是最高位变为1。
    源码存在的问题是存在正0和负0的问题,虽然+0 = -0,但是它们无法在二进制表示式上统一。
    同时正数和负数的加法运算不容易实现。
1 =>  0 000 0001
-1 => 1 000 0001
  • 反码
    正数的反码就是原码。
    负数的反码是将负数的符号位之外的所有比特位全部取反。
1 =>  0 000 0001
-1 => 1 111 1110
  • 补码
    正数的补码就是原码。
    负数的补码将负数的符号位之外的所有比特位全部取反,然后加1的和。
    大多数计算机使用的都是补码表示法,但有过反码表示的计算机。
    C语言标准没有明确规定必须使用补码表示法,Java则明确规定了必须使用补码表示法。
1 =>  0 000 0001
-1 => 1 111 1111

补码完美解决和加法问题和0的统一表示问题。

基本位运算

  • &(与运算)
    与运算就是将两个数的补码按照二进制位(包括符号位)一次做与规则运算。
    与规则是:两数同时为1返回1;否则则返回0.
0 & 0 = 0;0 & 1 = 0;1 & 0 = 0;1 & 1 = 1;
3 & 5 -> 0011 & 0101 = 0001 
因此 3 & 5 = 1
  • ~(取反运算)
    取反运算是将这个数的补码按照二进制位(包括符号位)依次取反。
    即0取反=1,1取反=0.
~(-1) = 0
~ 1 =  -2
  • |(或运算)
    或运算是将这个数的补码按照二进制位(包括符号位)做或规则运算。
    或规则:两数同时为0,返回0;否则返回1.

  • ^(异或运算)
    异或运算是将两个数的补码按照二进制位(包括符号位)做异或规则运算。
    异或规则:
    两数不同返回1,两数相同返回0.

3 ^ 5 = 6
0011 ^ 0101 = 0110
  • 位移运算符号
<<(左移运算符)和<<<(无符号左移)
  <<(左移运算符):
    将一个数的补码,除开符号位,其余位置的数据向左依次移动。
    左边溢出的数据忽略,而低位(即右边空出来的位置)数据补0.
    溢出即超出这个数据类型的最大长度。
  <<<(无符号左移):即连同符号位一起左移。
   因为是2进制表示,所以一般而言,左移返回此数乘以2的值。

>>(右移运算符)和>>>(无符号右移)
  >>(右移运算符):
     将一个数的补码,除开符号位,其余位置的数据向右依次移动。
     右边溢出的数据忽略,而高位(即左边空出来的位置)数据补0.
  >>>(无符号右移):即连同符号位一起右移。
     因为是2进制表示,所以一般而言,右移返回此数除以2的值。

常用位运算

位运算的优先级比算术运算的优先级高。

  • 乘法和出发
    一般用左/右移运算符计算以2为倍数的结果。

  • 取低位和高位
    利用&运算进行取位运算。
    取低位:n & 0x0000FFFF;取高位:n & 0xFFFF0000。
    取低x位:n & (1 << x -1 );取x高位:n & (~(1 << x))<<(31 - x)。
    这里Integer类型除开符号位,二进制值位的长度是31.

  • 正负判断
    (n >>> 31) & 1,等于0为正,等于1为负。

  • 取余
    n % m ,如m为2的幂次方,可用(n & (m - 1))替代。

  • 通用四则运算的实现
    https://blog.csdn.net/ojshilu/article/details/11179911

注意

  • 溢出
    溢出是指当前值超过的其数据类型的最大和最小范围,从而使值得结果不准确。
    只有当两个相同符号数相加,而运算结果的符号与原数据符号相反时,产生溢出
    其他情况,不会产生溢出。

参考

https://blog.csdn.net/coffeelifelau/article/details/52433653

你可能感兴趣的:(j2se)