快速模幂运算,帮我找出错误

时间:2016-11-13 20:37:52

标签: python algorithm

我正在尝试实现快速取幂的方案。学位以二进制形式表示:

def pow_h(base, degree, module):
    degree = bin(degree)[2:]
    r = 1

    for i in range(len(degree) - 1, -1, -1):
        r = (r ** 2) % module
        r = (r * base ** int(degree[i])) % module

    return r

但功能不正常,哪里出错?

formula

2 个答案:

答案 0 :(得分:1)

如果当前指数是偶数或奇数,那么这种快速取幂必须采取不同的行为,但是你的代码中没有这样的检查。以下是一些提示:

要查找x**y,您需要一个"累加器"变量来保存到目前为止计算的值。让我们使用a。因此,您发现a*(x**y)代码正在减少y并且增加a和/或x,直到y变为零并且a是您的最终答案。

如果y是偶数,请说y==2*k,然后a*x**(2*k) == a*(x**2)**k。这使y减少到y//2并将x增加到x**2

如果y为奇数,请说y==2k+1,然后a*x**(2*k+1) == (a*x)*x**(2*k)。这使y减少到y-1并将a增加到a*x

你应该可以从这里算出算法。我没有使用模数:这应该很容易。

答案 1 :(得分:1)

正如我在评论中所说,内置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