位运算的操作:https://bits.stephan-brumme.com/
负数是按照补码的形式参与按位与运算的
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.(1为正,0为负)
反码的表示方法是:
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
补码的表示方法是:
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
为什么会有反码和补码呢?是为了让符号位也能参与运算,我们就不需要判断符号位了
为了解决0和-0问题,出现了补码,机器中的计算是使用补码计算的
一.按位与运算符
1.进行清零计算(将一个单元与0进行位与运算结果为零)
2.获取一个数中指定的位(例如取X=1010 1101的低四位 则将X&00001111得到0000 1101)
3.判断奇偶性(任意数与1取位与,结果为1则是奇数)
4.取余操作
#include<iostream>
using namespace std;
int main()
{
int a = 16;
int b = 25;
// 取余
cout<<(a & 3)<<endl; // 除以4的余数
cout<<(a & 7)<<endl; // 除以8的余数
cout<<(a & 8)<<endl; // 无效,只能运算2的次幂的余数
return 0;
}
二.取反运算符
1.变换符号
变换符号就是正数变成负数,负数变成正数。
如对于-11和11,可以通过下面的变换方法将-11变成11
1111 0101(二进制) –取反-> 0000 1010(二进制) –加1-> 0000 1011(二进制)
同样可以这样的将11变成-11
0000 1011(二进制) –取反-> 0000 0100(二进制) –加1-> 1111 0101(二进制)
因此变换符号只需要取反后加1即可。
2.求绝对值
位操作也可以用来求绝对值,对于负数可以通过对其取反后加1来得到正数。对-6可以这样:
1111 1010(二进制) –取反->0000 0101(二进制) -加1-> 0000 0110(二进制)
来得到6。
因此先移位来取符号位,int i = a >> 31;要注意如果a为正数,i等于0,为负数,i等于-1。然后对i进行判断——如果i等于0,直接返回。否之,返回~a+1。
int my_abs(int a)
{
int i = a >> 31;
return i == 0 ? a : (~a + 1);
}
三.按位或运算符
负数按补码形式参加按位或运算。
1.对某些位置进行置1操作
如将X=1010 1010的第四位置1,则将X |0000 1111得到1010 1111
四.异或运算符
1.交换两个数
void Swap(int &a, int &b)
{
if (a != b)
{
a ^= b;
b ^= a;
a ^= b;
}
}
2.一个数异或两次还是自己,可以用来进行加密,异或两次得自己,异或一次就得0
3.使特定位翻转找一个数,对应X要翻转的各位,该数的对应位为1,其余位为零,此数与X对应位异或即可。
例:X=10101110,使X低4位翻转,用X ^0000 1111 = 1010 0001即可得到。
4.与0异或得到原值
例:X=10101110,用X^0=10101110
五.左移右移
左移1位乘以2,左移n位乘以2^n;
右移1位除以2,右移n位除以2^n;