GMPY2(或GMP)有pow()函数吗?

9 投票
3 回答
7606 浏览
提问于 2025-04-18 06:52

GMPY2(或者叫GMP)有一个叫做powmod的函数,但我找不到除了Python自带的pow以外的其他普通幂运算的函数。请问有没有类似的函数可以用在mpz整数上?

3 个回答

1

当然可以

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(还有这个)。

2

一些性能信息:

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实际上是完全一样的。

10

你只需要用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() 等函数也是一样的道理。

撰写回答