Python 数字幂的整数除法可以优化吗?

Python 数字幂的整数除法可以优化吗?,python,built-in,pow,Python,Built In,Pow,Python中有一个内置函数pow,它优化了a**b%c的计算。为什么没有计算a**b//c的函数 我将尝试在这里总结为什么a**b//c的计算不能优化,不太可能a**b%c 先决条件:计算a**b%c 让我们举一个示例:假设a=2和b=11。如果我们假设它相当慢,那么我们可以推断出b=1+2+8=2**0+2**1+0*2**2+2**3。在此之后,此推断可作为结果相乘的规则a,a**2,a**4,a**8。将前一个结果平方后指定每个结果。最后,a**11=a*(a**2)*(a**8)这个过

Python中有一个内置函数
pow
,它优化了
a**b%c
的计算。为什么没有计算a**b//c的函数

我将尝试在这里总结为什么
a**b//c
的计算不能优化,不太可能
a**b%c

先决条件:计算
a**b%c
让我们举一个示例:假设
a=2
b=11
。如果我们假设它相当慢,那么我们可以推断出
b=1+2+8=2**0+2**1+0*2**2+2**3
。在此之后,此推断可作为结果相乘的规则
a
a**2
a**4
a**8
。将前一个结果平方后指定每个结果。最后,
a**11=a*(a**2)*(a**8)
这个过程只需要3次平方运算

如果我们推广这个过程,可以这样做:

a, b, r = 2, 11 , []

while b>0:
    if b % 2: r.append(a)
    b = b//2
    a = a*a
else:
    if b % 2: r.append(a)

print(r)
输出是
r=[2,4,256]
。接下来,我们需要乘以这些乘数。可以使用functools import reduce中的
命令
reduce(lambda x,y:x*y,r)
完成此操作

最后,如果乘法器变得非常大,那么乘法器变得非常慢,因此我们需要将每个乘法器
m
替换为其模
m%c
,并在
reduce
函数中执行相同的操作。最后,我们有:

from functools import reduce
def pow(a, b, c):
    # returns a ** b % c
    r = []
    while b > 0:
        if b % 2: r.append(a)
        b = b // 2
        a = (a * a) % c
    else:
        if b % 2: r.append(a)

    return reduce(lambda x, y: (x * y) % c, r)
输出是
4
,因为
2**11%7
4

我也在我的电脑上测试了结果
2046457**1103207%71872
。输出为
18249
,计算耗时9秒,而
pow(204645711032071872)
立即给出相同的结果

更新:将
a**b//c
插入计算 按照上述想法,我将尝试对
a**b//c
的计算进行类似的优化。我假设平方的过程保持不变,这里的主要区别是我们需要考虑积分和残差部分,同时采取正方形(以前是容易的,因为积分部分并不重要)。如果
x
是一个不可分割的部分,而
y
是剩余部分,则我们有一个关系:

我们还需要为两个不同的乘数引入类似的计算:

我的脚本现在看起来像这样:

from functools import reduce
def pow(a, b, c):
    #returns tuple (a ** b // c,  a ** b % c)
    print(f'calculating: {a}**{b} = ', end='')
    r = []
    ir = (a//c, a%c) # we keep integral and residual part of a instead of a
    while b > 0:
        if b % 2: r.append(ir)
        b = b // 2
        ir = (ir[0]*ir[0]*c + 2*ir[0]*ir[1]+ (ir[1]*ir[1])//c, (ir[1]*ir[1]) % c)
    else:
        if b % 2: r.append(ir)
    out = reduce(lambda x, y: (c*x[0]*y[0] + x[0]*y[1] + x[1]*y[0] + (x[1] * y[1])//c, (x[1] * y[1]) % c), [(2, 2)]+[r[-1]])

    print(' * '.join(str(n[0]*c+n[1]) for n in r), end=' = ')
    print(' * '.join(str(n) for n in r),'=', out)
    return out

pow(2,7,3)
输出 笔记 为什么现在还不是呢?我们可以看到,每个因子中的第二项始终很小,但这不是第一项的规则,如本例中的
pow(26,31,35)


在这种情况下,我们无法避免
a%b//c
的指数增长。这就是为什么
a%b//c
没有内置函数对我来说似乎是合理的。

这不是在博客(或白皮书)上更常见吗?在这方面你似乎不需要帮助……我在这里发布了一个类似问题的变体:@Oliver.R分享知识你已经发现自我回答的目的就是要用艰难的方式。(这一特定因素的有用性可能有争议;但“其他人会面临这个问题吗”也不是常规问题的标准。)@millimoose Fair points,谢谢你的见解-mathfux我为我不必要的评论道歉!
calculating: 2**7 = 2 * 4 * 16 = (0, 2) * (1, 1) * (5, 1) = (42, 2)
calculating: 26**31 = 26 * 676 * 456976 * 208827064576 * 43608742899428874059776 = 
(0, 26) * (19, 11) * (13056, 16) * (5966487559, 11) * (1245964082840824973136, 16) = 
(89709413964539398065824, 32)