Python是如何实现内置函数pow()的?
我必须编写一个程序来计算Python是如何实现内置函数pow()的?,python,algorithm,math,Python,Algorithm,Math,我必须编写一个程序来计算a**b%c,其中b和c都是非常大的数字。如果我只使用a**b%c,速度非常慢。然后我发现内置函数pow()可以通过调用pow(a,b,c) 我很想知道Python是如何实现这一点的?或者在哪里可以找到实现此函数的源代码文件?Python在一般情况下使用C数学库,在某些概念(如无穷大)中使用它自己的逻辑。的第1426行显示了实现math.pow的Python代码,但基本上,它可以归结为调用标准C库,该库可能具有该函数的高度优化版本 Python在进行密集的数字运算时可能会
a**b%c
,其中b
和c
都是非常大的数字。如果我只使用a**b%c
,速度非常慢。然后我发现内置函数pow()
可以通过调用pow(a,b,c)
我很想知道Python是如何实现这一点的?或者在哪里可以找到实现此函数的源代码文件?Python在一般情况下使用C数学库,在某些概念(如无穷大)中使用它自己的逻辑。的第1426行显示了实现math.pow的Python代码,但基本上,它可以归结为调用标准C库,该库可能具有该函数的高度优化版本
Python在进行密集的数字运算时可能会非常慢,但可以给您带来相当快的速度提升,尽管它不如调用标准库的C代码好。我不了解Python,但如果您需要快速幂,可以通过平方使用幂运算:
这是一种简单的递归方法,使用了指数的可交换性。如果
a
、b
和c
是整数,则在每个步骤(包括第一步)中,通过减少模c
可以提高实现效率(即,在开始之前减少a
模c
)。这就是真正的功能。该函数有200多行代码,因为它必须处理引用计数,并处理负指数和一系列特殊情况
但是,该算法的核心思想相当简单。假设我们要计算正整数a
和b
,并且b
具有二进制数字b_i
。然后我们可以将b
写成
b = b_0 + b1 * 2 + b2 * 2**2 + ... + b_k ** 2**k
a ** b = a**b0 * (a**2)**b1 * (a**2**2)**b2 * ... * (a**2**k)**b_k
ansa**b
as
b = b_0 + b1 * 2 + b2 * 2**2 + ... + b_k ** 2**k
a ** b = a**b0 * (a**2)**b1 * (a**2**2)**b2 * ... * (a**2**k)**b_k
本产品中的每个因素的形式为<代码>(a**2**i)**b_i。如果b_i
为零,我们可以简单地忽略因子。如果b_i
为1,因子等于a**2**i
,可以通过反复平方a
来计算所有i
的幂。总的来说,我们需要平方和乘k
次,其中k
是二进制di>的数目吉特的b
以上,对于<代码> PoW(a,b,c)我们可以在每一步中减少模<代码> c>代码>平方和乘法之后。
您可以考虑以下两种实现来计算<代码>(x**y)%Z快速。< /P> Python中的:def pow_mod(x, y, z):
"Calculate (x ** y) % z efficiently."
number = 1
while y:
if y & 1:
number = number * x % z
y >>= 1
x = x * x % z
return number
#include <stdio.h>
unsigned long pow_mod(unsigned short x, unsigned long y, unsigned short z)
{
unsigned long number = 1;
while (y)
{
if (y & 1)
number = number * x % z;
y >>= 1;
x = (unsigned long)x * x % z;
}
return number;
}
int main()
{
printf("%d\n", pow_mod(63437, 3935969939, 20628));
return 0;
}
在C语言中:
def pow_mod(x, y, z):
"Calculate (x ** y) % z efficiently."
number = 1
while y:
if y & 1:
number = number * x % z
y >>= 1
x = x * x % z
return number
#include <stdio.h>
unsigned long pow_mod(unsigned short x, unsigned long y, unsigned short z)
{
unsigned long number = 1;
while (y)
{
if (y & 1)
number = number * x % z;
y >>= 1;
x = (unsigned long)x * x % z;
}
return number;
}
int main()
{
printf("%d\n", pow_mod(63437, 3935969939, 20628));
return 0;
}
#包括
无符号长功率模块(无符号短x、无符号长y、无符号短z)
{
无符号长数=1;
while(y)
{
如果(y&1)
编号=编号*x%z;
y>>=1;
x=(无符号长)x*x%z;
}
返回号码;
}
int main()
{
printf(“%d\n”,pow_mod(634373393596993920628));
返回0;
}
在Python中实现pow(x,n)
def myPow(x, n):
p = 1
if n<0:
x = 1/x
n = abs(n)
# Exponentiation by Squaring
while n:
if n%2:
p*= x
x*=x
n//=2
return p
def myPow(x,n,m):
p = 1
if n<0:
x = 1/x
n = abs(n)
while n:
if n%2:
p*= x%m
x*=x%m
n//=2
return p
def myPow(x,n):
p=1
如果cpython源repo位于Objects/longobject.c:long_pow()(正如JimB已经评论的那样)。math.pow()
没有模参数,并且与内置的pow()不是同一个函数
。另外,仅供参考,Psyco变得非常陈旧,并且没有64位支持。NumPy对于严肃的数学非常有用。@Noctis,我尝试运行您的Python实现,得到了以下结果:TypeError:ufunc“bitwise”和“not supported for the input type,并且根据强制转换规则“safe”,无法安全地将输入强制为任何受支持的类型------如下我现在正在学习Python,我想您可能知道这个错误(搜索表明它可能是一个bug,但我认为有一个快速的解决方法)@stackuser:在下面的演示中,它似乎工作得很好:有人能解释为什么这个解决方案有效吗?我很难理解这个算法背后的逻辑。@NoctisSkytower,考虑到本机pythonpow()
内置函数也支持这一点,而且似乎更快?>>st_pow='pow(65537L,767587L,14971787L)>>>st_pow mod='pow mod(65537L,767587L,14971787L)>>timeit.timeit(st_pow)4.510787010192871>>timeit.timeit(st_pow mod,def_pow mod)10.135776996612549
@Fabiano我的函数不应该被使用。它只是解释Python如何在场景后面工作,而没有参考C语言的源代码。我试图回答wong2关于pow
是如何实现的问题。为什么我们可以在每个步骤中使用模C来减少?@BenSandler:因为≡ a'(模块c)和b≡ b’(模c)表示ab≡ a'b'(mod c),或者换句话说,先将a和b模c减然后乘,还是先将它们乘然后再减模c都无关紧要。请参见。请注意,long\u pow
现在在该文件的另一行定义:@JohanC我已经更新了包含提交哈希的链接,因此它不再过时。