私は、ルーカス・レーマーの素数判定を実装しようとしています。
私は2つの実装、JavaでC ++およびその他の1は、これらのは次のですしました:
C ++:
int p = 86243;
cpp_int M;
bit_set(M, p);
M = M-1; // M = 2^p - 1;
cpp_int S;
S = 4;
while(p>2) {
S = pow(S, 2);
S -= 2;
S %= M;
p--;
}
Javaの:
int p = 86243;
BigInteger M = BigInteger.ZERO;
BigInteger Two = BigInteger.valueOf(2L);
M = M.setBit(p);
M = M.subtract(BigInteger.ONE); // M = 2^p - 1;
BigInteger S = BigInteger.valueOf(4L);
while(p>2) {
S = S.pow(2).subtract(Two).mod(M);
p--;
}
Javaコードは、私は、JavaのためのコードブロックとEclipseを使用していますC ++のために、はるかに高速C ++コードよりも実行されます。
そのための任意の理由は?私は特にC ++のコードで何か足りませんか?任意の提案は理解されるであろう。
私はあなたが両方のプログラム(JavaとC ++のバージョン)が同等であることを期待すべきではないと思います。パフォーマンスは、ほとんどの言語ではなく、使用されるアルゴリズムに依存します。プロファイラショーでC ++のバージョンを実行しデバイド(つまりMOD)がボトルネックであること。あなたはその後、除算(/boost/multiprecision/cpp_int/divide.hpp)のソースを見れば、あなたはこのコメントを見ることができます:
非常に単純な、かなり長い部門を脳死。[...]特定の参照Knuthの巻2に、この利用可能なより効率的なアルゴリズムが存在する。なおしかしながら肢の少数のため、これは一般的代替案を凌駕し、余分なストレージを必要とする正規化ステップを回避します。
JavaでのBigIntegerの実装は、しかし、クヌースおよび/またはBurnikelZieglerと呼ばれるアルゴリズムを使用しています。これらは、より多くの方が適しているように思えます。パフォーマンスが重要な場合は、GNU多精度ライブラリ(GMP)を使用しようとすることができます。私のマシンではGMPのバージョンはおよそ3倍に高速のJava / BigIntegerをより次のとおりです。
#include <iostream>
#include <gmp.h>
using namespace std;
int main()
{
int p = 86243;
mpz_t M;
mpz_init(M);
mpz_set_ui(M, 0);
mpz_setbit(M, p);
mpz_sub_ui(M, M, 1); // M = 2^p - 1;
mpz_t S;
mpz_init(S);
mpz_set_ui(S, 4);
while(p > 2) {
mpz_pow_ui(S, S, 2);
mpz_sub_ui(S, S, 2);
mpz_mod(S, S, M);
p--;
}
int r = mpz_get_ui(S);
cout << "Is mersenne prime: " << (r == 0 ? "yes" : "no") << endl;
return 0;
}
-lgmpとリンク