问题描述
对于以下两个 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*A
和 A*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 这样的多精度库。