猜拳游戏中利用数字规律优化算法为何实测性能更优?
为何取模优化的猜拳算法比暴力枚举更快?
背景
我近期阅读一本计算机入门书籍,书中给出猜拳游戏的两种实现:用整数0、1、2分别代表石头、剪刀、布。
暴力枚举实现
最直接的方式是枚举所有3×3=9种情况,代码片段如下:
import random as rand a = rand.randint(0, 2) b = rand.randint(0, 2) if a == 0 and b == 0: print("draw game") elif a == 0 and b == 1: print("winner is A") # ... 剩余6种分支省略
取模优化实现
作者提示用数学技巧简化代码,利用数字间的关系减少分支,代码如下:
import random as rand a = rand.randint(0, 2) b = rand.randint(0, 2) if a == b: print("draw game") elif a == (b + 1) % 3: print("winner is B") else: print("winner is A")
预期与实测反差
我原本认为两者性能差异不大,甚至暴力枚举可能更优——因为取模操作看起来比==比较消耗更多CPU周期。但通过$ time python3 game.py测试后,发现取模算法运行更快。
为排除rand.randint(0, 2)和print()的性能干扰,我做了针对性测试:
- 预生成所有测试用例存入列表
- 用
pass替代print()减少IO开销 - 重复执行100万次测试循环
测试代码框架如下:
def brute_force(a, b): if a == 0 and b == 0: pass # ... 剩余8种分支省略 def mod(a, b): if a == b: pass elif a == (b + 1) % 3: pass else: pass if __name__ == '__main__': testcases = [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)] num_repetitions = 1_000_000 for i in range(num_repetitions): for a, b in testcases: brute_force(a, b) # 切换注释测试另一种算法:mod(a, b)
测试结果
- 暴力枚举算法的time测试样本(单位:秒):[17.014, 18.069, 16.956, 17.931, 17.919, 17.211, 17.983, 16.984, 17.581, 17.048]
- 取模算法的time测试样本:[15.921,14.817,15.723,15.715,15.715,16.917,14.957,15.196,16.115,14.763]
疑问
明明包含取模操作,为什么取模优化后的算法实测性能反而比暴力枚举更优?
内容的提问来源于stack exchange,提问作者da_miao_zi
相关产品推荐
相关产品推荐

