C++ 如何加速这个素性测试
我想找出给定数的最大素因子。经过几次尝试,我已经增强了测试,以应对相当大的数字(即10亿毫秒)。现在的问题是,如果超过10亿,那么执行时间可以说是永远的。我想知道我是否可以做更多的改进,减少执行时间。我希望有更好的执行时间,因为在这个链接中,执行时间非常快。我现在的目标号码是600851475143。代码是相当不言自明的注意:我考虑过Eratosthenes算法的筛选,但在执行时间方面没有运气C++ 如何加速这个素性测试,c++,primes,C++,Primes,我想找出给定数的最大素因子。经过几次尝试,我已经增强了测试,以应对相当大的数字(即10亿毫秒)。现在的问题是,如果超过10亿,那么执行时间可以说是永远的。我想知道我是否可以做更多的改进,减少执行时间。我希望有更好的执行时间,因为在这个链接中,执行时间非常快。我现在的目标号码是600851475143。代码是相当不言自明的注意:我考虑过Eratosthenes算法的筛选,但在执行时间方面没有运气 #include <iostream> #include <cmath> b
#include <iostream>
#include <cmath>
bool isPrime(int n)
{
if (n==2)
return true;
if (n%2==0)
return false;
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
if (n%i==0)
return false;
return true;
}
int main()
{
int max(0);
long long target(600851475143);
if( target%2 == 0 )
max = 2;
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
}
std::cout << "The greatest prime common factor is " << max << "\n";
return 0;
}
#包括
#包括
bool isPrime(int n)
{
如果(n==2)
返回true;
如果(n%2==0)
返回false;
对于(inti(3);i我可以看到的一个明显的优化是:
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
我认为这可能导致加速的原因是sqrt
处理浮点算术运算
,而编译器通常在优化浮点算术运算方面并不慷慨。gcc有一个特殊的标志来明确地启用浮点优化
对于达到您提到的目标范围的数字,您需要更好的算法。应该足够了
下面是代码(),它几乎不需要花费任何时间来完成:
int main() {
long long input = 600851475143;
long long mx = 0;
for (int x = 2; x <= input/x; ++x){
while(input%x==0) {input/=x; mx = x; }
}
if (input > 1){
mx = input;
}
cout << mx << endl;
return 0;
}
intmain(){
长-长输入=600851475143;
长mx=0;
对于(int x=2;x 1){
mx=输入;
}
请注意,除了2和3之外,所有素数都与6的倍数相邻
以下代码将总迭代次数减少了:
- 利用上述事实
- 每次发现新的素因子时,减少
target
#包括
布尔检查因子(长-长和目标,长-长因子)
{
如果(目标%系数==0)
{
do目标/=因子;
而(目标百分比系数==0);
返回true;
}
返回false;
}
长GetMaxFactor(长目标)
{
长最大因子=1;
if(检查系数(目标,2))
maxFactor=2;
if(检查系数(目标,3))
最大因子=3;
//仅检查与6的倍数相邻的系数
对于(长-长系数=5,相加=2;系数*系数1)
回报目标;
返回最大因子;
}
int main()
{
长目标=600851475143;
std::coutfor(inti(3);i您不需要素性测试。请尝试以下算法:
function factors(n)
f := 2
while f * f <= n
if n % f == 0
output f
n := n / f
else
f := f + 1
output n
功能因子(n)
f:=2
而f*f这是我的基本版本:
int main() {
long long input = 600851475143L;
long long pMax = 0;
// Deal with prime 2.
while (input % 2 == 0) {
input /= 2;
pMax = 2;
}
// Deal with odd primes.
for (long long x = 3; x * x <= input; x += 2) {
while (input % x == 0) {
input /= x;
pMax = x;
}
}
// Check for unfactorised input - must be prime.
if (input > 1) {
pMax = input;
}
std::cout << "The greatest prime common factor is " << pMax << "\n";
return 0;
}
intmain(){
长输入=600851475143L;
长pMax=0;
//处理质数2。
while(输入%2==0){
输入/=2;
pMax=2;
}
//处理奇数素数。
用于(长x=3;x*x1){
pMax=输入;
}
std::我们可以尝试使用更高级的算法,比如。旁白:sqrt
是一个浮点函数;您依赖它返回准确的结果,但它不能保证返回准确的结果。@Hurkyl而且在任何情况下,他都应该测试i*i@Alnitaki,顺便说一句:)显然,最大的优化是通过确保原始数字除以找到的每个因子来实现的。这在这里解释得很糟糕。此外,您真正想要的x*x应该是auto maxFactor=static_cast(sqrt(n))
;这样,每次比较都不会将i
提升为float
。还有一种非常快速的方法,可以不使用浮点而获得平方根的整数部分。@Spencer根本不需要执行任何平方根操作。如果单独处理2,则可以将循环所花费的时间减半,而不必使用浮点运算。@Spencer然后从x=3
开始循环,并增加2。对于这个特定的数字,i
的大小无关紧要,因为它将获得的最大值将适合短的。鉴于你似乎知道基本测试,我很惊讶你没有完全消除sqrt
调用。@Alnitak:600851475143
适合于short
??为什么我要取消对函数sqrt
的调用?除数适合于short,而不是被分解的数字。你应该取消对sqrt的调用,因为与I*I
与n
@Alnitak相比,它的成本非常高。这是一个函数调用O(n)
乘法。你怎么能如此确定后者总是更有效?@Alnitak:无论如何……我已经完全改变了我的答案。因为,OP正在为完全相同的(最终)执行两个相同“量级”的独立循环出于这个目的,我决定不尝试改进他/她的解决方案,而是提出一个新的解决方案。
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
function factors(n)
f := 2
while f * f <= n
if n % f == 0
output f
n := n / f
else
f := f + 1
output n
int main() {
long long input = 600851475143L;
long long pMax = 0;
// Deal with prime 2.
while (input % 2 == 0) {
input /= 2;
pMax = 2;
}
// Deal with odd primes.
for (long long x = 3; x * x <= input; x += 2) {
while (input % x == 0) {
input /= x;
pMax = x;
}
}
// Check for unfactorised input - must be prime.
if (input > 1) {
pMax = input;
}
std::cout << "The greatest prime common factor is " << pMax << "\n";
return 0;
}
long long limit = iSqrt(input)
for (long long x = 3; x <= limit; x += 2) {
if (input % x == 0) {
pMax = x;
do {
input /= x;
} while (input % x == 0);
limit = iSqrt(input); // Value of input changed so reset limit.
}
}