如前所述,您的第一个问题是
int mod_func(int p, int g, int x) {
return ((int)pow((double)g, (double)x)) % p;
}
是pow(g,x)
经常超出int
范围,然后您有未定义的行为将该结果转换为int
,无论结果int
是什么,都没有理由相信它与所需的模数有任何关系。
下一个问题是pow(g,x)
as a的结果double
可能不准确。除非是 2 的幂,否则即使它在范围内,对于足够大的指数g
,数学结果也不能精确表示为 a ,但如果数学结果可以精确表示(取决于 的实现),它也可能发生。double
pow
如果您进行数论计算 - 并且计算幂模整数的余数是一 - 您应该只使用整数类型。
对于手头的情况,您可以通过重复平方来使用取幂,计算所有中间结果的残差。如果模数p
足够小而(p-1)*(p-1)
不会溢出,
int mod_func(int p, int g, int x) {
int aux = 1;
g %= p;
while(x > 0) {
if (x % 2 == 1) {
aux = (aux * g) % p;
}
g = (g * g) % p;
x /= 2;
}
return aux;
}
可以。如果p
可以更大,则需要使用更宽的类型进行计算。