位运算
前言
学习位运算前要先了解二进制 -> 十进制
,十进制 -> 二进制
。
二进制 -> 十进制
例:20 = 16 + 4
(没有考虑符号位实际是-20)
这里解释一下符号位
以一个字节8比特位类型为例
20
的二进制为10100
不满足八位,所以从前面补零为00010100
,最前面为符号位 正数为0,负数为1。
-20 表示为10010100
(这里不用过度纠结,负数在计算机是以补码(后面会讲)形式存在)
十进制 -> 二进制
例:30 = 11110
一、原码,反码,补码
简明扼要就是二进制不同表型形式。
1.负数的原码,反码,补码
原码 -> 反码, 符号位不变,其余取反.
反码 -> 补码, 反码基础上,加1,补码才是计算机中存储的二进制数
2.正数的原码,反码,补码
正数的补码和反码均与原码相同,
二、位运算符
1.按位 与 &
参与计算的两个二进制数,对应位如果
同为1
结果为1
,否则结果为0
.
例: 3 & 5 = 1
结论: x x x & y y y ≤ m a x ( x , y ) \leq max(x , y) ≤max(x,y)
2.按位 或 |
参与计算的两个二进制数,对应位如果
有一个为1
结果为1
,否则结果为0
.
例: 2 | 4 = 6
结论: x x x ∣ | ∣ y y y ≥ m a x ( x , y ) \geq max(x , y) ≥max(x,y)
3.按位 取反 ~
参与运算的一个二进制数,把
1变0
,0变1
.
-x = ( ~x + 1 )
(由下列可得)
以5为例:
原码: 00000101
反码: 00000101
补码: 00000101
以-5为例
原码: 10000101
反码: 11111010
补码: 11111011
4.按位 取异或 ^
俗称:不进位加法。
参与计算的两个二进制数,对应位如果
不等
则结果为1
,否则
结果为0
.
例 6 ^ 7 = 1
5.左移 <<
例: i << j,
i
在二进制中的所有位向左移动j
个位置 ,而右边填0.
每左移一位
二进制位上
对应的十进制数就会被 * 2.(只针对正数)例:
一个数对应的
二进制2位
上是1
,则它对应的十进制
数是2 ^ 2 * 1
,
将其左移一个位移到二进制3位上
那么它对应的十进制
为2 ^ 3 * 1
.
6.右移 >>
例: i >> j,
i
在二进制中的所有位向右移动j
个位置.
每右移一位
二进制位上
对应的十进制数就会被 / 2.(只针对正数)例:
一个数对应的
二进制2位
上是1
,则它对应的十进制
数是2 ^ 2 * 1
,
将其右移一个位移到二进制1位上
那么它对应的十进制
为2 ^ 1 * 1
.
三、位运算的应用
1.n的二进制表示第k位是几
1.先把
n
的第k
位移到最后一位x = n >> k
(二进制位数从0开始,例:二进制01
,0是1位
,1是0位
)
看最后一位是几x & 1
例:求5的二进制表示,不足八位补0
代码如下:
#include<iostream>
using namespace std;
int main()
{
int n = 5;
for (int i=7; i>=0; i--)
cout << ( n >> i & 1);
}
2.lowbit()函数
lowbit(x)
返回x
二进制最后一位1.
例: 十进制表示(二进制表示)
5 (101) , lowbit (5) = 1 (1) ; (1为101的最后一位1)
12 (1100) , lowbit (12) = 4 (100) ; (100为1100的最后一位1)
lowbit函数 代码如下():
int lowbit(int n)
{
return n & -n;
}
总结
这是我第一次写博客,花了自己很长时间,以后自己会再接再厉.