位操作基本运算符
位操作的基本运算符有:与,或,取反,异或,左移,右移。
要会使用位操作运算符,就不得不先对计算机存储数字的方式有一定的了解。
原码:原码是二进制的一种编码方式,其中最前面的一位叫做符号位——0代表正数,1代表负数,其余为表示值。用一个8位的二进制数举例。
原码很好理解,我们可以很容易知道它表示的二进制数,但是它不方便计算机的运算,所以补码就诞生了。
补码:补码是一个数存储在计算机中的真正形式,而原码则是现实数字和计算机中数字的一个过渡,桥梁。
下面是补码与原码的转换关系:
正数:正数的补码就是原码
负数:负数的补码是它的绝对值的原码对每一位进行取反操作(0变1,1变0)所得到的数再加1。如,-1的绝对值为1,1的原码为00000001,对000000001取反后得到11111110,最后加上1得到11111111,11111111这个数就是-1的补码。
补码将减法运算可以等同于加法运算,比如:
特殊情况:
得到的补码不能再转化成原码(结果不对),但是我们的把这个特殊的补码当作-128来看待。
位操作符的应用(位操作的每一个数都是补码形式):
1. 判断奇偶数
oid judge(int num) { if (num & 1) //奇数运算的结果为1,偶数则为0 cout << "奇数" endl; else cout << "偶数" << endl; }
2. 交换两个数
void Swap(int &a, int &b) { if (a != b) { a ^= b; b ^= a; a ^= b; } }
原理解释:假设a 中 存储的数字为A,b 为 B。
a ^ = b 等价于 a = a ^ b, 即 a = A ^ B;
b ^ = a 等价于 b = B ^ (A ^ B) ,因为异或运算符满足交换律,所以B ^ (A ^ B) = (B ^ B) ^ A,容易知道,对两个相同的数进行异或操作对于0(...0000000),而0和任意一个数进行异或操作对于这个数本身,所以b = A;
同理:a ^ = b 等价于 a = B;
所以,a和b两个变量中存储的值发生的交换。
3.变换符号
int change_sign(int a) { return ~a + 1; }
原理解释:由补码的知识我们知道,负数补码由由其对应的正数的补码(正数补码 = 原码)取反后得到,即~a + 1,如果要从正数得到负数则为~(a - 1)。~a + 1 与 ~(a - 1) 的结果一致,所以无论是一个数的符号变化都可以通过~a + 1实现。
4.判断正负数
void judge(int num) { if (num >> 31) cout << "负数"; else cout << "正数"; }