実行時間:JavaのBigIntegerの対ブーストマルチ精度

User_67128:

私は、ルーカス・レーマーの素数判定を実装しようとしています。

私は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とリンク

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=335621&siteId=1