isPrime函数的改进
Improvements for isPrime function
互联网上有很多问题需要你找到素数,所以我决定写一组函数来找到它们。我使用Eratosthenes的筛来生成素数,因为与其他算法相比,它快速且易于实现。然而,我想知道我的代码而不是方法是否效率低下。我用的是STL容器/迭代器吗?我的代码中有没有放慢程序速度的部分?
换句话说,它确实正确地计算了结果,但我想知道的是,它的效率是否可以通过一些算法的改进来提高,而不仅仅是一些代码调整。
任何帮助都将不胜感激。
这是我的代码(如果很难阅读,我深表歉意)
#include <iostream>
#include <set>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define initial_prime_barrier 100
bool isFlagged(int i) { return i == 0; }
bool isNextStart(int i) { return i != 0; }
vector<int> generatePrimesBelow(int limit)
{
vector<int> primes;
for (int i = 2; i < limit; i++)
{
primes.push_back(i);
}
vector<int>::iterator currentStart = primes.begin();
do
{
int numberAtStart = *currentStart;
vector<int>::iterator currentNumber = currentStart + numberAtStart;
do
{
*currentNumber = 0;
advance(currentNumber, numberAtStart);
} while (currentNumber < primes.end());
currentStart = find_if(currentStart + 1, primes.end(), isNextStart);
} while ((*currentStart) * (*currentStart) < limit);
vector<int>::iterator newEnd = remove_if(primes.begin(), primes.end(), isFlagged);
primes.erase(newEnd, primes.end());
return primes;
}
bool isPrime(int number)
{
static vector<int> primes = generatePrimesBelow(initial_prime_barrier);
static int numPrimes = primes.size();
static int largestPrime = primes[numPrimes-1];
static int halfwayPrime = primes[numPrimes/2];
if (number == largestPrime)
{
return true;
}
else if (number < largestPrime)
{
if (number == halfwayPrime)
{
return true;
}
else if (number > halfwayPrime)
{
for (int i = numPrimes/2; i < numPrimes; i++)
{
if (number == primes[i])
{
return true;
}
}
}
else if (number < halfwayPrime)
{
for (int i = numPrimes/2; i >= 0; i--)
{
if (number == primes[i])
{
return true;
}
}
}
}
else if (number > largestPrime)
{
primes = generatePrimesBelow(number + number);
numPrimes = primes.size();
largestPrime = primes[numPrimes-1];
halfwayPrime = primes[numPrimes/2];
return isPrime(number);
}
return false;
}
int main (int argc, char * const argv[])
{
const int number = 123123;
cout << (isPrime(number) ? "YES" : "NO") << endl;
}
是的,这是您的方法。有几件事。你不需要你的数组来保存数字,数组中每个条目的地址都是数字本身。您只需要它们保存两个值——true
和false
。所以,让你的阵列vector<bool>
,它会更加紧凑。然后,在你的内部循环中,你从x+x
开始,并按照x
的步骤前进。您应该从x*x
开始,按照2*x
的步骤前进,这将适用于除2
之外的所有x
。将其设为特殊情况,或者在初始化循环中标记这些偶数。或者将CCD_ 10处的条目视为表示数字CCD_。这应该会加快你的筛选代码。最后,您不需要特殊的find_if
调用及其所有机制,只需检查循环中出现的当前条目即可。
(编辑:)在isPrime
中,您手动执行二进制搜索,但STL中已经有一个二进制搜索算法。如果您保持vector<bool>
筛阵列不变,而不压缩,您就根本不需要它。那么CCD_ 15只需要检查索引CCD_ 16处的数组值是否仍然是CCD_。
(编辑2:)现在,关于效率。您重新计算到n+n
,可能是因为预计会有更多的数字需要测试。如果你只测试少数人,简单的赔率划分会更快。如果要测试的数字都在一个狭窄的上部区域,您的最佳选择是偏移筛,下部筛直到测试区域上限的sqrt
。如果数字分布广泛,那么可以使用当前的全阵列方法。
这里要使用的关键事实是,在值上m
以下大约有n ~= m/log m
素数,从0
到m
筛选数组需要O(m*log (log m))
时间,而通过r=sqrt b
以下的所有素数筛选a
和b
之间的上部区域,即宽度为d=b-a
,需要与d*log (log r)
成比例的时间。
此外,当增加你的筛子阵列时,最好是扩大,而不是重新计算整个。素数都在那里。为了筛选附属部分,有必要循环通过筛阵列中的所有素数,直到其新上边缘的sqrt
。这让人想起分段筛,尽管每个新的分段都代替了前一个分段,或者在任何情况下都与前一个分开。
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- isPrime函数的改进
- 如何在c++中重用函数(如isPrime、isEven、isPalindome)