原码、反码、补码
原码
原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。原码是人脑最容易理解和计算的表示方式。
[+1]原= 0000 0001
[-1]原= 1000 0001
取值范围:[1111 1111 , 0111 1111]
- [-127 , 127]
反码
正数的反码是其本身;负数的反码是在其原码的基础上,符号位不变,其余各个位取反。可见如果一个反码表示的是负数,人脑无法直观的看出来它的数值。通常要将其转换成原码再计算。
[+1] = [0000 0001]原= [0000 0001]反
[-1] = [1000 0001]原= [1111 1110]反
取值范围
- [-127, +127]
补码
正数的补码就是其本身;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1。(也即在反码的基础上+1);对于负数,补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码再计算其数值。
[+1] = [0000 0001]原= [0000 0001]反= [0000 0001]补
[-1] = [1000 0001]原= [1111 1110]反= [1111 1111]补
取值范围
- [-128, 127]
位运算
与&
或|
异或^
取反~
左移
<< 带符号左移
右移
>>带符号右移
>>> 无符号右移- 负数有影响
小技巧
-
判断奇偶数
- n & 1 == 1
-
交换俩个数
-
例如 a = 9 ,b = 10
-
a =a ^b
- c = a^b
-
b = a^b
- d = c^b = abb = a^0 = a
-
a = a^b
- e = c^d = cad = aba = b
-
-
-
二进制枚举
for(int i=0;i<(i<<n);i++) // 范围0~ 2^n - 1
{
for(int j =0 ;j<n;i++) // 遍历二进制的每一位,共n位
{
if(i&(1<<j)){ //判断当前值i 二进制值得第j位是否为1
// 操作
}
}
}
- 加法
int add(int num1,int num2){
int a = num1 ^ num2
int b = num1 & num2
b = b <<1
if (b==0) return a
return add(a,b)
}
-
平均数
- avg = a&b + ((a^b)>>1)
-
二进制中1的个数
-
int 型数字,则遍历32次, n & (1<<i ) 为1 则n的二进制值第i 位为1
-
n = n & (n -1 ) while n > 0
- n & (n -1 ) 会抵消 n 二进制的最后一个 1
-