(以下在jupyter notebook进行)
1、位运算
1. 原码、反码和补码
二进制有三种不同的表示形式:原码、反码和补码,计算机内部使用补码来表示。
原码:就是其二进制表示(注意,有一位符号位且符号位是最高位)。
In [ ]:
00 00 00 11 -> 3 10 00 00 11 -> -3
反码:正数的反码就是原码,负数的反码是符号位不变,其余位取反(对应正数按位取反)。
In [ ]:
00 00 00 11 -> 3 11 11 11 00 -> -3
补码:正数的补码就是原码,负数的补码是反码+1。
In [ ]:
00 00 00 11 -> 3 11 11 11 01 -> -3
符号位:最高位为符号位,0表示正数,1表示负数。在位运算中符号位也参与运算。
总结: 1、符号位为最高位,且仅有一位,0表示正数,1表示负数。在位运算中符号位也参与运算。 2、正数的原码是二进制,其补码和反码都是原码。 3、负数的反码为符号位不变,其余位对应正数按位取反,负数的补码是反码+1。
2. 按位运算
1、按位非操作 ~
In [7]:
~ 1 01->1 10->-2
Out[7]:
-2
In [9]:
~0 0->0 1->-1
Out[9]:
-1
总结:~ 把num的补码中的 0 和 1 全部取反(0 变为 1,1 变为 0)有符号整数的符号位在 ~ 运算中同样会取反。
In [ ]:
00 00 01 01 -> 5 ~ --- 11 11 10 10 -> -6 11 11 10 11 -> -5 ~ --- 00 00 01 00 -> 4
2、按位与操作 &
In [12]:
1 & 1 01 01 ->01 ->1
Out[12]:
1
In [13]:
1 & 0 01 00 ->00 ->0
Out[13]:
0
In [14]:
0 & 1 00 01 ->00 ->0
Out[14]:
0
In [15]:
0 & 0
Out[15]:
0
总结:只有两个对应位都为 1 时才为 1
In [ ]:
00 00 01 01 -> 5 & 00 00 01 10 -> 6 --- 00 00 01 00 -> 4
3、按位或操作 |
In [16]:
1 | 1 01 01 ->01->1
Out[16]:
1
In [17]:
1 | 0
Out[17]:
1
In [18]:
0 | 1
Out[18]:
1
In [20]:
2 | 3 010->2 | 011->3 --- 011->3
Out[20]:
3
总结:只要两个对应位中有一个 1 时就为 1
In [ ]:
00 00 01 01 -> 5 | 00 00 01 10 -> 6 --- 00 00 01 11 -> 7
4、按位异或操作
In [21]:
1 ^ 1 01 -> 1 ^ 01 -> 1 --- 00 -> 0
Out[21]:
0
In [22]:
1 ^ 0 01 ->1 ^ 00 -> 0 --- 01 ->1
Out[22]:
1
In [23]:
0 ^ 1 00 -> 0 ^ 01 -> 1 --- 01 -> 1
Out[23]:
1
总结:只有两个对应位不同时才为 1
In [ ]:
#eg: 00 00 01 01 -> 5 ^ 00 00 01 10 -> 6 --- 00 00 00 11 -> 3
异或操作的性质:满足交换律和结合律
A: 00 00 11 00 B: 00 00 01 11
A^B: 00 00 10 11 B^A: 00 00 10 11
A^A: 00 00 00 00 A^0: 00 00 11 00
A^B^A: = A^A^B = B = 00 00 01 11
5、按位左移操作 <<
num << i 将num的二进制表示向左移动i位所得的值。
In [ ]:
00 00 10 11 -> 11 11 << 3 --- 01 01 10 00 -> 88
6、按位右移操作 >>
num >> i 将num的二进制表示向右移动i位所得的值。
In [ ]:
00 00 10 11 -> 11 11 >> 2 --- 00 00 00 10 -> 2
3. 利用位运算实现快速计算
1、通过 <<,>> 快速计算2的倍数问题。
In [ ]:
n << 1 -> 计算 n*2 n >> 1 -> 计算 n/2,负奇数的运算不可用 n << m -> 计算 n*(2^m),即乘以 2 的 m 次方 n >> m -> 计算 n/(2^m),即除以 2 的 m 次方 1 << n -> 2^n
2、通过 ^ 快速交换两个整数。 通过 ^ 快速交换两个整数。
In [ ]:
a ^= b b ^= a a ^= b
3、通过 a & (-a) 快速获取a的最后为 1 位置的整数。
In [ ]:
00 00 01 01 -> 5 & 11 11 10 11 -> -5 --- 00 00 00 01 -> 1 00 00 11 10 -> 14 & 11 11 00 10 -> -14 --- 00 00 00 10 -> 2
4. 利用位运算实现整数集合
一个数的二进制表示可以看作是一个集合(0 表示不在集合中,1 表示在集合中)。
比如集合 {1, 3, 4, 8},可以表示成 01 00 01 10 10 而对应的位运算也就可以看作是对集合进行的操作。
元素与集合的操作:
In [ ]:
a | (1<<i) -> 把 i 插入到集合中 a & ~(1<<i) -> 把 i 从集合中删除 a & (1<<i) -> 判断 i 是否属于该集合(零不属于,非零属于)
集合之间的操作:
In [ ]:
a 补 -> ~a a 交 b -> a & b a 并 b -> a | b a 差 b -> a & (~b)
注意:整数在内存中是以补码的形式存在的,输出自然也是按照补码输出。
In [ ]:
#例子C#语言输出负数。 class Program{ static void Main(string[] args){ string s1 = Convert.ToString(-3, 2); Console.WriteLine(s1); // 11111111111111111111111111111101 string s2 = Convert.ToString(-3, 16); Console.WriteLine(s2); // fffffffd } }
In [27]:
#【例子】 Python 的bin() 输出。 print(bin(3)) # 0b11 print(bin(-3)) # -0b11 print(bin(-3 & 0xffffffff)) # 0b11111111111111111111111111111101 print(bin(0xfffffffd)) # 0b11111111111111111111111111111101 print(0xfffffffd) # 4294967293
0b11 -0b11 0b11111111111111111111111111111101 0b11111111111111111111111111111101 4294967293
是不是很颠覆认知,我们从结果可以看出:
1、Python中bin一个负数(十进制表示),输出的是它的原码的二进制表示加上个负号,巨坑。 2、Python中的整型是补码形式存储的。 3、Python中整型是不限制长度的不会超范围溢出。
所以为了获得负数(十进制表示)的补码,需要手动将其和十六进制数0xffffffff进行按位与操作,再交给bin()进行输出,得到的才是负数的补码表示。
2、条件语句
1. if 语句
In [ ]:
if expression: expr_true_suite
1、if 语句的 expr_true_suite 代码块只有当条件表达式 expression 结果为真时才执行,否则将继续执行紧跟在该代码块后面的语句。 2、单个 if 语句中的 expression 条件表达式可以通过布尔操作符 and,or和not 实现多重条件判断。
In [29]:
if 2 > 1 and not 2 > 3: print('Correct Judgement!') # Correct Judgement!
Correct Judgement!
2. if - else 语句
In [ ]:
if expression: expr_true_suite else: expr_false_suite
Python 提供与 if 搭配使用的 else,如果 if 语句的条件表达式结果布尔值为假,那么程序将执行 else 语句后的代码。
In [31]:
temp = input("猜一猜小姐姐想的是哪个数字?") guess = int(temp) # input 函数将接收的任何数据类型都默认为 str。 if guess == 666: print("你太了解小姐姐的心思了!") print("哼,猜对也没有奖励!") else: print("猜错了,小姐姐现在心里想的是666!") print("游戏结束,不玩儿啦!")
猜一猜小姐姐想的是哪个数字?666 你太了解小姐姐的心思了! 哼,猜对也没有奖励! 游戏结束,不玩儿啦!
if语句支持嵌套,即在一个if语句中嵌入另一个if语句,从而构成不同层次的选择结构。
In [32]:
#【例子】Python 使用缩进而不是大括号来标记代码块边界,因此要特别注意else的悬挂问题。 hi = 6 if hi > 2: if hi > 7: print('好棒!好棒!') else: print('切~') # 无输出
In [33]:
#【例子】 temp = input("猜一猜小姐姐想的是哪个数字?") guess = int(temp) if guess > 8: print("大了,大了") else: if guess == 8: print("你太了解小姐姐的心思了!") print("哼,猜对也没有奖励!") else: print("小了,小了") print("游戏结束,不玩儿啦!")
猜一猜小姐姐想的是哪个数字?8 你太了解小姐姐的心思了! 哼,猜对也没有奖励! 游戏结束,不玩儿啦!
3. if - elif - else 语句
if expression1: expr1_true_suite elif expression2: expr2_true_suite . . elif expressionN: exprN_true_suite else: expr_false_suite
elif 语句即为 else if,用来检查多个表达式是否为真,并在为真时执行特定代码块中的代码。
In [35]:
#【例子】 temp = input('请输入成绩:') source = int(temp) if 100 >= source >= 90: print('A') elif 90 > source >= 80: print('B') elif 80 > source >= 60: print('C') elif 60 > source >= 0: print('D') else: print('输入错误!')
请输入成绩:60 C
4. assert 关键词
assert这个关键词我们称之为“断言”,当这个关键词后边的条件为 False 时,程序自动崩溃并抛出AssertionError的异常
In [ ]:
#【例子】 my_list = ['lsgogroup'] my_list.pop(0) assert len(my_list) > 0 # AssertionError
In [ ]:
#【例子】在进行单元测试时,可以用来在程序中置入检查点,只有条件为 True 才能让程序正常工作。 assert 3 > 7 # AssertionError