言われているように、あなたの最初の問題は
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の結果double
が正確でない可能性があることです。が2の累乗でない限り、数学的な結果は、範囲内であっても十分に大きい指数g
として正確に表すことはできませんが、数学的な結果が正確に表現できる場合にも発生する可能性があります(の実装によって異なります)。double
pow
数論的計算を行い、整数を法とする留数を計算する場合は、整数型のみを使用する必要があります。
手元のケースでは、すべての中間結果の残差を計算して、2乗を繰り返すことでべき乗を使用できます。モジュラス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
大きくできる場合は、計算に幅の広いタイプを使用する必要があります。