Python 的 pow() 函数和快速求幂给出了不同的答案

问题描述

对于以下两个 C 和 python 实现,我得到了不同的答案。 在 Python 中

print(pow(15,47413144071,94826288143))

打印 1

但是在 C 中

#include<stdio.h>
unsigned long Power(unsigned long A,unsigned long B,unsigned long X)
{
    unsigned long res = 1;
    while( B > 0 )
    {
        if( B & 1UL )
        {
            res = ( res * A ) % X;
        }
        A = ( A * A ) % X;
        B >>= 1UL;
    }
    return res;
}
int main()
{
    printf("%lu",Power(15,94826288143));
    return 0;
}

印刷品: 893231448 感谢任何帮助。

解决方法

如注释中所述,unsigned long 仅保证值最大为 4294967295,并且您的 B 和 X 更大,否则您将获得值 mod 2^32 mod X 而不是值 mod X。对于输入,您可以用 unsigned long long 替换它们。

然而,您不仅需要 B 和 X 可以表示为 unsigned long long,还需要 res*AA*A,因为 A 可以和 { 一样大{1}} 在 C 中使用 X-1 是不够的。

,

这里证明您的 C 代码即使使用 uint64_t 类型也会产生溢出。

我刚刚将 C 代码转换为 Python,添加了溢出测试。第一个不能表示为 uint64_t 的值是 2**64 或 0x10000000000000000 或 18446744073709551616。所以我在 mod 操作之前测试了所有产品:

def Power(A,B,X):
    res = 1
    step = 1
    while (B > 0):
        if B & 1:
            if (res * A) >= 0x1000000000000000:
                print("uint64_t overflow at res step",step)
            res = (res * A) % X
        if (A * A) >= 0x1000000000000000:
            print("uint64_t overflow at A step",step)
        A = (A * A) % X
        B >>= 1
        step += 1
    return res

>>> Power(15,47413144071,94826288143)
uint64_t overflow at A step 4
uint64_t overflow at A step 5
uint64_t overflow at A step 6
uint64_t overflow at A step 7
uint64_t overflow at A step 8
uint64_t overflow at A step 9
uint64_t overflow at res step 10
uint64_t overflow at A step 10
uint64_t overflow at A step 11
uint64_t overflow at res step 12
uint64_t overflow at A step 12
uint64_t overflow at A step 13
uint64_t overflow at res step 14
uint64_t overflow at A step 14
uint64_t overflow at A step 15
uint64_t overflow at A step 16
uint64_t overflow at res step 17
uint64_t overflow at A step 17
uint64_t overflow at res step 18
uint64_t overflow at A step 18
uint64_t overflow at A step 19
uint64_t overflow at res step 20
uint64_t overflow at A step 20
uint64_t overflow at A step 21
uint64_t overflow at A step 22
uint64_t overflow at A step 23
uint64_t overflow at A step 24
uint64_t overflow at A step 25
uint64_t overflow at res step 26
uint64_t overflow at A step 26
uint64_t overflow at A step 27
uint64_t overflow at res step 28
uint64_t overflow at A step 28
uint64_t overflow at A step 29
uint64_t overflow at A step 30
uint64_t overflow at A step 31
uint64_t overflow at A step 32
uint64_t overflow at res step 33
uint64_t overflow at A step 33
uint64_t overflow at res step 34
uint64_t overflow at A step 34
uint64_t overflow at A step 35
uint64_t overflow at res step 36
uint64_t overflow at A step 36
1

这肯定证明算法是正确的(我们最终得到 1),但如果您尝试使用 64 位整数,也会出现大量溢出。


长话短说,如果您需要在 C 中实现它,您需要一个具有 uint128_t 类型的系统,或者使用像 gmplib 这样的多精度库。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...