移位的应用整理

移位的应用整理

移位运算的概念

移位针对的对象是二进制数据
为什么计算机要使用补码存储数据:补码存储的原因

//例如int类型5在计算机中存储为 0000 0000 0000 0000 0000 0000 0000 0101

移位运算符
<< 左移:左边丢弃,右边补0
>> 右移:算术右移,右边丢弃,左边补原来的符号位;逻辑右移,右边丢弃,左边补0
&:按位与,按位与&,1与1为1,1与0,0与0均为0
|:按位或,按位或|,1或1为1,1或0为1,0或0为0
^:异或,相同为0,相异为1
~:按位取反,0转1,1转0

移位的应用场景

判断奇偶性

奇数存储在计算机中的补码最低位一定是1,而偶数存储在计算机中的补码最低位一定是0,因此可以与1按位运算区别奇数还是偶数

a&1   = 0 偶数             //2的补码 0000 0000 0000 0000 0000 0000  0000 0010
a&1   = 1 奇数             //3的补码 0000 0000 0000 0000 0000 0000  0000 0011

c语言运算符优先级总结请点这里

取int型变量a的第K位(k=0,1,2……sizeof(int))

a>>k&1

将int型变量的第k位置1

a=a|(1<<k)

将int型变量a的第k位清0

a=a&~(1<<k)

int型变量循环左移k次

(sizeof(int)=16)
a=a<>16-k   

int型变量a循环右移k次

(sizeof(int)=16)
a=a>>k|a<<16-k

整数的平均值

对于两个整数x,y,如果用 (x+y)/2 求平均值,有可能会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的。

int average(int x, int y)   //返回x,y 的平均值
{   
     return (x&y)+((x^y)>>1);
}

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

boolean power2(int x)
{
    return ((x&(x-1))==0)&&(x!=0)}

用位运算符交换两个整数

这个是一种比较特殊的交换数据的方式,不需用第三个容器来交换数据。

void swap(int x , int y)
{
    x ^= y;
    y ^= x;
    x ^= y;
}

例如:x=10,y=6;

x: 0000 0000 0000 0000 0000 0000 0000 1010

y: 0000 0000 0000 0000 0000 0000 0000 0110

x=x^y: x= 0000 0000 0000 0000 0000 0000 0000 1100

y=y^x: y= 0000 0000 0000 0000 0000 0000 0000 1010

x=x^y: x= 0000 0000 0000 0000 0000 0000 0000 0110

计算绝对值

int abs( int x )
{
  int y ;
  y = x >> 31 ;
  return (x^y)-y ;        //or: (x+y)^y
}

取模运算转化成位运算(在不产生溢出的情况下)

a % (2^n) 等价于 a & (2^n - 1)

乘法运算转化成位运算

利用了数据在计算机中存储的形式特点,数据左移n位就是变为原来的2^n倍

a * (2^n) 等价于 a<< n

例如:int a=10; a*=2^3;

计算机中补码形式为(0000 0000 0000 0000 0000 0000 0000 1010)

a*=2^3;(0000 0000 0000 0000 0000 0000 0101 0000)

即,补码有效数据左移3位,数据变为原来2^3倍。

除法运算转化成位运算 (在不产生溢出的情况下)

a / (2^n) 等价于 a>> n

判断赋值

if (x == a)        //等价于 x= a ^ b ^ x;
    x= b;
else
    x= a;             
 

x的相反数

利用了正负数在计算机中补码的性质。

 (~x+1)

参考:c语言按位运算的妙用

你可能感兴趣的:(c语言)