最近,学校模电课上学习了数字电路,接触了一些位运算有关的东西,觉得挺好的,就想记下来做个笔录。
Title:基础位运算
Author:zhuangyue_lala
Key words:位运算,C++
在学校开设的C++课上老师并没有讲位运算,当初觉得挺复杂的,也没有关注这一点。最近在学习了模电课之后,从计算机组成及操作方面对位运算有了一定了解之后,深刻觉得位操作是个好东西,于是就来查查资料,自学并梳理了一下。
本文决定从以下几个方面展开:
(一)二进制
(二)基础位操作运算符与运算规则
(三)位运算的简单应用
(一)首先,第一方面。什么是二进制?计算机处理二进制数的方法。以一个字节为例,一个字节有8byte,可以表示256个整数,从-128~127,以最高位为符号位,0代表整数,1代表负数,定义0的二进制数为00000000,那么1的二进制就是00000001,而01111111就代表127,从00000001到01111111就是从1到127。那么负数是怎么存的呢?是不是就是将正数符号位换成1就可以了呢?这样的话你会发现,你取不到-128。要知道负数在计算机中是怎样存的,先要介绍一下源码,反码,补码,以-1为例,-1的原码是00000001,就是它绝对值的二进制数,将每一个位取反就得了它的反码,再将反码+1就得到了补码。-1的补码就是11111111,由此,我们发现从10000000到11111111分别表示-128到-1。负数再计算机中存储方式就是补码。所以对其位操作的时候,需要对其补码进行操作,千万不要用源码。
(二)接下来,就是常见的位运算符号以及法则。这里给出一个表格。
这里强调一下:1、只有取反是 单目运算符,其他的都是双目运算符
2、位运算的优先级比较低,所以最好能加上括号,以免得出不知所以然的值。
3、位操作只能处理整形数,不能处理double和float,这是由存储方式决定的
4、在移位操作中,左移都是低位补零,右移根据编译器决定,高位补符号位和高位补零两种。前一种叫算数移位,后一种叫逻辑移位。一般在VC,vs采用的就是算数移位。
(三)接下来就是一些实用的位运算小技巧,虽然不能起到实际上的质变,也能在同学面前装装逼的,当然实际上的目的是学着用一下位运算。
1、判断奇偶。
一个二进制数判断奇偶太简单了,末尾0偶,1奇,没有别的可能了,所以,只要找到这个数的最低位就可以了。可以用if(a&1)代替if(a%2)来寻找奇数。
2、交换两数。一般的写法如下:
void Swap(int &a, int &b)
{
if (a != b)
{
int c = a;
a = b;
b = c;
}
}
那,可不可以不用引入参数就可以完成数据交换!,位操作写法如下:
void Swap(int &a, int &b)
{
if (a != b)
{
a ^= b;
b ^= a;
a ^= b;
}
}
首先要知道,一个数和自己异或是零。一个数和零异或是它本身。
第一步,a=(a^b);
第二步,b=b^(a^b),由于异或运算具有交换性,所以第二部等同于b^b^a=a,此时b就得到了a的值了。
第三步,a=(a^b)^b,和刚才一样,注意此时b已经是a的值了,由此a就得到了b的值。
3、取反。
变换符号就是负变正,正变负。在操作之前要判断是正是负。用移位操作来完成,将a>>31,a为正数的话,表达式的值为0,否则表达式的值为1。
将一个整数取反然后加一就得到相反数。
比如7=00000111,~7=11111000,+1之后,11111001,这就是-7了哈
再回来一遍11111001取反,00000110,加一00000111,得7。
很奇妙不是吗?
int SignReversal(int a)
{
return ~a + 1;
}
int main()
{
printf("对整数变换符号 --- by MoreWindows( http://blog.csdn.net/MoreWindows ) ---
");
int a = 7, b = -12345;
printf("%d %d
", SignReversal(a), SignReversal(b));
return 0;
}
4、取绝对值,跟上一个基本一样,不多说了。
其实,位运算最大的优点就是压缩运行空间,试想,位操作是直接对byte位进行操作,比用字节位操作要整整轻松了八分之一,很厉害。但是位操作也不是哪都用的,因为它会让代码的可读性变差很多,在写最底层程序的时候,用位还是挺多的。这就是这次学习的收获。