GMPY2(或GMP)有pow()函数吗?
GMPY2(或者叫GMP)有一个叫做powmod
的函数,但我找不到除了Python自带的pow
以外的其他普通幂运算的函数。请问有没有类似的函数可以用在mpz
整数上?
3 个回答
当然可以。
void mpz_pow_ui (mpz_t rop, const mpz_t base, unsigned long int exp)
void mpz_ui_pow_ui (mpz_t rop, unsigned long int base, unsigned long int exp)
这个函数会把 rop 设置为 base 的 exp 次方。特别地,0 的 0 次方结果是 1。
其实并没有一个叫 mpz_pow(...)
的函数可以接受两个 mpz_t
类型的输入。原因是,记忆中好像是因为 unsigned long
类型已经足够用了,而如果用 mpz_t e, b
来表示 b^e
,在内存需求上可能会很容易超出范围。我找不到提到这个的邮件列表帖子,但如果找到的话我会把链接发上来。
补充:我好像找不到一个没有模运算的纯 pow
函数用于 Python,可能是我没有认真找。不过我看到有一个 sqrt
函数,这意味着你可以自己实现一个 pow
(还有这个)。
一些性能信息:
gmpy2库里的pow函数比Python自带的pow函数快一倍,即使考虑到构建的时间:
>>> timeit.timeit('pow(98765, 10)', number=100000)
0.048412954514788
>>> timeit.timeit('pow(gmpy2.mpz(98765), 10)', number=100000, setup='import gmpy2')
0.024286470230094892
你可以在mpz类型上使用内置的pow(x,y,modulus)
,但使用powmod会快大约10%。
>>> timeit.timeit('pow(gmpy2.mpz(987654321),1000,100003)',
number=100000, setup='import gmpy2')
0.057212181510976734
>>> timeit.timeit('gmpy2.powmod(987654321,1000,100003)',
number=100000, setup='import gmpy2')
0.04513445007546579
>>> timeit.timeit('pow(987654321,1000,100003)',
number=100000, setup='import gmpy2')
0.15511784474188062
gmpy2版本的速度比Python自带的在有模数的情况下快得多(有时快到10倍)。使用powmod比使用pow/mpz只快一点,因为mpz的构建时间会影响速度。
如果你已经有了一个mpz,powmod和pow实际上是完全一样的。
你只需要用Python自带的 pow()
函数或者用指数运算符 **
就可以了。GMPY2的 mpz
类型重载了所有标准的特殊方法,所以你可以直接使用Python的标准命令。
比如说:
>>> from gmpy2 import mpz
>>> pow(mpz(3),7)
mpz(2187)
>>> pow(mpz(3),7,13)
mpz(3)
>>> mpz(3)**7
mpz(2187)
>>>
对于 divmod() 等函数也是一样的道理。