位运算
位运算指的是直接对二进制进行操作,来达到运算结果;
特点:运算高效,只能对整数进行操作;
与: &
或: |
异或: ^
一个数异或另外一位数两次,还是等于这个数本身;
//实现两个数的互换
int a=5,b=6;
a=a^b;
b=a^b;
a=a^b;
取反: ~
左移: <<
把整数的各二进制位全部向左移动n位,高位丢弃,包括符号位,低位补“0”;
对于无符号位来说,左移n位其实就是*2^n;
右移: >>
把整数的各二进制位全部右移n位,符号位不变,正数高位补“0”,负数一般补“1”;
对于无符号位来说,右移n位其实就是/2^n;
********注意:如果除数大于本身,正数为“0”,负数为“1”;
需求:利用位运算判断奇偶性
分析:一个数&1=1是奇数,&1=0就是偶数
int a;
if(a&1==1){
printf("a是奇数");
}else{
printf("a是偶数");
}
需求:编写一个整数的二进制表现形式
分析:把一个数从最高位&1,后一个一个地打印出来;
for(int i=31;i>0;i--){
printf("%d",(a>>i)&1);//让a先从最高位&1起,一直到最低位
}
二进制与原码、反码、补码
***********注意:CPU存储负数是以补码的形式存储的。。。
8个bit采用2’sComplement表示法,
负数的取值范围是从10000000到11111111(-128~-1),
正数是从00000000到01111111(0~127)。
首先,原码,反码,补码是一个真值用二进制表示的的不同方式。将一个真值表示成二进制字串的机器数的过程就称为编码。无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。
原码:数值的二进制表现形式;
*例如:
[+7]原=0 000 0111B
[-7]原=1 000 0111B
*注意:0的原码有两种形式
[+0]原=0 000 0000B
[-0]原=1 000 0000B
反码(除符号外的取反 ~ 运算):正数的反码与其原码相同,负数的反码是对其原码逐位取反,但符号除外;
*例如:
[+7]反=0 000 0111B
[-7]反=1 111 1000B
*注意:0的反码也有两种形式
[+0]反=0 000 0000B
[-0]反=1 111 1111B
*补码:正数的补码与其原码相同,负数的补码是在其反码的末位+1;
例如:
[+7]补=0 000 0111B
[-7]补=1 111 1001B(-7)的反码如上,
[+0]补=[-0]补=0 000 0000B
*模的概念:
把一个计量单位称之为模或模数。
例如:
时钟是以12进制的计数循环的,即以12为模。在时钟上,时针加上(正拨)12的整数位或减去(反拨)12的整数位,时钟的位置不变;
也就是说,从0点开始,(逆时针)减去10小时的位置相当于(顺时针)加上2小时,即2点(0-10=-10=-10+12=2),因此,在模为12的前提下,-10可映射为+2。
所以,在以12为模的计数系统下,-10的运算都可以用+2来代替;10和2对模12而言互为补数。
补码在微型机中是一种重要的编码方形,请注意:
采用补码后,可以方便地将减法转化成加法运算,运算过程得到简化;正数的补码即是它所表示的数的真假,而负数的补码的数值部分却不是它所表示 的数的真假;采用补码进行运算,所得的结果仍为补码;以上面时钟为例,也就是说:-10+2的补码等效于(+2+2)
与原码、反码不同,数值0的补码只有一个,即它本身;
若字长为8位,则补码所表示的范围为-128——+127或(0——255);进行补码运算时,应注意所得结果不应超过补码所能表示数的范围;相当于9[原]-6[原]=9[补]+6[补]=9+(256-6)=259,因为259已经超出了模位,所以必须再用259-256=3;*****注意:千万不要忘记”0——255是有256个数”***** |
|