我正在尝试实施Lucas-Lehmer素数测试。
我有两种实现,一种是C ++,另一种是Java,如下:
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代码的运行速度比C ++代码快得多,对于C ++,我正在使用CodeBlocks和Eclipse for Java。
任何原因吗?我是否特别缺少C ++代码中的任何内容? 任何建议将不胜感激。
答案 0 :(得分:4)
您可以使用内置的时钟功能检查比较。这是此C ++和Java代码的比较
C ++-> https://ideone.com/oj07xQ
Java-> https://ideone.com/MsAgil
您可以看到C ++花费了1193.19毫秒,而Java花费了2257.244454毫秒
您无法在CodeBlocks和Eclipse等不同的IDE上比较速度
#include<bits/stdc++.h>
#include <boost/multiprecision/cpp_int.hpp>
using boost::multiprecision::cpp_int;
using namespace std;
int32_t main() {
int start = clock();
int p = 8624;
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--;
}
// cout << S << endl;
int end = clock();
cout << "time: " << (end - start)/(double)(CLOCKS_PER_SEC)*1000 << " milliseconds\n";
}
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
long startTime = System.nanoTime();
int p = 8624;
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--;
}
// System.out.println(S);
long endTime = System.nanoTime();
System.out.println("Took "+(endTime - startTime) + " ns");
}
}
答案 1 :(得分:3)
我认为您不应该期望两个程序(Java和C ++版本)都等效。性能主要取决于所使用的算法,而不是语言。在事件探查器中运行C ++版本表明,鸿沟(即mod)是瓶颈。然后,如果您查看划分的来源(/boost/multiprecision/cpp_int/divide.hpp),您会看到以下注释:
非常简单,相当长的脑残。 [...] 请注意,有比这更有效的算法 可用,特别是参见Knuth Vol 2。 四肢的数量通常胜过其他选择 并避免了需要额外存储空间的标准化步骤。
但是Java中的BigInteger实现使用称为Knuth和/或BurnikelZiegler的算法。似乎这些更适合大量使用。如果性能确实很重要,则可以尝试使用gnu多精度库(gmp)。在我的计算机上,gmp版本大约比Java / BigInteger快3倍:
#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链接