基本概念

真值:

带符号位的机器数对应的真正数值称为机器数的真值
0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原码:

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值
PS:正数的原、反、补码都一样:0的原码跟反码都有两个,因为这里0被分为+0和-0。

反码:

正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反

补码:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补

PS:0的补码是唯一的,如果机器字长为8那么[0]补=00000000。

移码:

移码最简单了,不管正负数,只要将其补码的符号位取反即可。

例如:X=-101011 , [X]原= 10101011 ,[X]反=11010100,[X]补=11010101,[X]移=01010101


加法:

减法:

11 - 4 = 7

原码                                补码正数的补码
00001011 - 00000100 = 00001011 + 10000100 = 00001011 + 11111100 = 00000111 = 7 


4 - 11 = -7

原码 补码 负数的补码  补码反向
00000100 - 00001011 = 00000100 + 10001011 = 00000100 + 11110101 = 11111001 = 10000111 = -7

乘法:

例子

1101*11=1101*10+1101*1=11010+1101=100111


0101*0110 = 101*(0*1000)+101*(1*100)+101*(1*10)+101*0

  = 101*(0*10*10*10)+101*(1*10*10)+101*(1*10)+101*0

  = 0+(101<<2)+(101<<1)+0

最终乘法变成加法

除法:

位运算与优化_位运算符

除法变成减法进而转化成加法


位运算符

位操作符

&:按位与
|:按位或
^:按位异或(相同为1,不同为0)
~:取反()
<<:左移
>>:右移


~取反说明:

以int a=5为例 ~a=-6

过程

计算机中的数以补码形式表示

0000 0000 0000 0101           5的补码

1111 1111 1111 1010           取反

对补码再求补,得到原码

1000 0000 0000 0101+0000 0000 0000 0001=

1000 0000 0000 0110=-6

跟位运算符相关的优化操作


1操作int中的某一位

取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k&1 
将int型变量a的第k位清0,即a=a&~(1<<k) 
将int型变量a的第k位置1, 即a=a|(1<<k) 
将int型变量a的第k位取反, 即a=a^(1<<k) 

2 取余操作

对于x=2^n 的数取余可以用位操作代替   num%x = num&(x-1)

3 不引入临时变量交换两个变量的值

不引入第三变量,交换两个变量的值 (设 a=a1,b=b1) 
目 标          操 作              操作后状态 
a=a1^b1        a=a^b           a=a1^b1,b=b1 
b=a1^b1^b1   b=a^b           a=a1^b1,b=a1 
a=b1^a1^a1   a=a^b           a=b1,b=a1 

4 取绝对值

int abs(int x)
{
int y = 0;
y = x>>31;          //x为负时y=-1
return (x^y)-y;     //or: (x+y)^y
}

5 判断基偶 

基数 x&1 = 1
偶数 x&1 = 0

6 整数的平均值 

对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法: 
int average(int x, int y)  //返回X,Y 的平均值 
{    
    return (x&y)+((x^y)>>1); 
}

7 判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂 

boolean power2(int x) 

    return ((x&(x-1))==0)&&(x!=0); 
}  

二进制补码运算公式: (抄来的备用)

-x = ~x + 1 = ~(x-1) 
~x = -x-1 
-(~x) = x+1 
~(-x) = x-1 
x+y = x - ~y - 1 = (x|y)+(x&y) 
x-y = x + ~y + 1 = (x|~y)-(~x&y) 
x^y = (x|y)-(x&y) 
x|y = (x&~y)+y 
x&y = (~x|y)-~x 
x==y:    ~(x-y|y-x) 
x!=y:    x-y|y-x 
x < y:    (x-y)^((x^y)&((x-y)^x)) 
x <=y:    (x|~y)&((x^y)|~(y-x)) 
x < y:    (~x&y)|((~x|y)&(x-y))//无符号x,y比较 
x <=y:    (~x|y)&((x^y)|~(y-x))//无符号x,y比较