查缺补漏——位运算

编码方式

原码:第一位是符号位,后面是数字位。符号位 \(0\) 为正数,\(1\) 位负数

like tihs:
\(10000010\),这里表示的十进制数字就是 \(-2\),第一位 \(1\) 是符号位。


反码:
分两种情况:
1.正数的反码就等于正数的原码。
2.负数的反码就等雨负数的原码除了符号位,其余的位按位取反。

like this:
原码:\(00000010\) 反码:\(00000010\) (正数的反码就等于正数的原码。)
原码:\(10000010\) 反码:\(11111101\) (负数的反码就等于负数的原码除了符号位,其余的位按位取反。)


补码:
分两种情况:
1.正数的补码就等于正数的原码。
2.负数的补码就等于负数的原码除了符号位,其余按位取反之后+1。

like this:
原码:\(00000010\) 补码:\(00000010\) (正数的补码就等于正数的原码。)
原码:\(10000010\) 反码:\(11111110\) (负数的补码就等于负数的原码除了符号位,其余的位按位取反之后+1。)


Q1:为什么计算机运算用补码?

A:最近观看了b站上的一个叫“寒武纪魔道电子”的老师讲计算机运算器的。老师讲解是这样的:
因为一个字节的运算是会自然溢出的。就是说运算中超过最高位的数字可以直接舍弃。所以说,一个字节,不停给它+1,转回十进制表达的数字是循环的。

循环给我们的启示就是循环的数字相同的一定是在模循环节的长度的意义下是同余的。补码可以使用加法的电路进行减法而不会出错。

位运算

位运算的意义:位运算可以用来优化算法。位运算的速度比一般的运算快很多。在状态压缩时我们处理数据要使用位运算。

按位取反 ~

按位取反的符号是 ~。是一个数字的运算。如果这一位是 \(1\) 就变成 \(0\),是 \(0\) 就变成 \(1\)
具体如下:

1010001011   原数
0101110101   按位取反之后的结果

按位与 &

按位与是两个数之间的运算,这两个数字在这一位上都位 \(1\),则运算后的结果就是 \(1\),否则就结果就是 \(0\)
具体如下:

1001011011   原数a
0101110101   原数b
0001010001   按位与之后的结果

按位或 |

按位或是两个数之间的运算,只要这两个数字在这一位有一个为 \(1\),则运算后的结果就是 \(1\),否则就结果就是 \(0\)
具体如下:

1001011011   原数a
0101110101   原数b
1101111111   按位或之后的结果

异或 ^

异或是两个数之间的运算,在这一位上,若相同则为 \(0\),不同则为 \(0\)
具体如下:

0001011011   原数a
0101110101   原数b
0100101110   异或之后的结果

异或运算经常直接出现在算法题目当中,我们需要熟知它的性质:

1.异或满足交换律。
2.异或满足结合律。
3.根据异或的运算法则,异或有这样的性质:
    一) x^x=0
	二) x^0=0
根据这两条,可以推出异或操作是可逆的


其余的性质都可以根据这三条进行推导,更加详细的性质就不再列举。

右移 >>

左移和右移是极其有用的,一定要学好。在判断状压dp的状态时有重要的作用。

把一个数字的二进制位全部右移若干位,最低位抛弃。这时候左边要补位。如果这是一个正数的话,每右移一位,补一个 \(0\)。如果这个数是负数,每右移一位,左边补一个 \(1\)

66 >> 3
00111110
00011111 >>1
00001111 >>2
00000111 >>3
等于7

左移 <<

把一个数字的二进制位全部左移若干位,最高位抛弃。这时候右边要补位。每左移一位,右边补一个 \(0\)

12<<3
00001100
00011000 >>1
00110000 >>2
01100000 >>3
等于96

解语:
读者在读完之后可以去力扣上练一练,算法OJ上一般没有这种比较全的纯位运算练习。

作业:
1.使用位运算交换两个数的值(不使用中转数组)。
2.使用位运算计算一个数字的二进制位上的 \(1\) 出现的地方。

如果觉得好,就点个👍。

posted @ 2024-08-14 19:19  Ruan_ji  阅读(20)  评论(0)    收藏  举报