pow
函数已经实现了快速模指数,但是我认为自己实现它是一个合理的编码练习。base
而不是r
,并且你应该在乘法步骤之后进行平方。def pow_h(base, degree, module):
degree = bin(degree)[2:]
r = 1
for i in range(len(degree) - 1, -1, -1):
r = (r * base ** int(degree[i])) % module
base = (base ** 2) % module
return r
#test
for i in range(16):
print(i, 2**i, pow_h(2, i, 100))
输出
0 1 1
1 2 2
2 4 4
3 8 8
4 16 16
5 32 32
6 64 64
7 128 28
8 256 56
9 512 12
10 1024 24
11 2048 48
12 4096 96
13 8192 92
14 16384 84
15 32768 68
使用r * base ** int(degree[i])
是一个巧妙的技巧,但使用if
语句可能更有效率,而且可以使用算术来获取degree
的位,而不是使用字符串,尽管bin
非常高效。无论如何,这是我的版本:
def pow_h(base, power, modulus):
a = 1
while power:
power, d = power // 2, power % 2
if d:
a = a * base % modulus
base = base * base % modulus
return a
power, d = divmod(power, 2)
来代替。 - chepnerdivmod
是因为它的优雅性,但在我的timeit
测试中,我发现divmod(a, b)
比仅使用a // b, a % b
稍微慢一些。但那是在Python 2.6上,在一台相当老的机器上进行的测试,所以你的情况可能会有所不同。 - PM 2Ring//-%
的速度是 divmod
的 1-15 倍。这个范围以及 divmod
时间保持稳定的事实表明可能存在缓存或测试设置不佳的情况,因此我选择了一个更中立的评论。 - chepner
print()
以查看您得到的值,并将其与纸上的计算进行比较。 - furaspow
函数接受一个模数作为可选的第三个参数。 - PM 2Ring