找到质数的有效方法
Efficient way of finding Primes
我有一个循环,它从3到两个用户输入的素数(这些数字可以是任何长度)的phi,找到这两个素数之间的所有素数,并将它们存储到一个数组中。
我的循环代码:int coPrimes(int num)
{
for (int i=3; i<=num; i++)
if(isPrime(i))
coprimes.push_back(i);
这个循环需要很长时间才能完成。
Enter a prime number for 'a': 601
Enter a prime number for 'b': 769
a value: 601
b value: 769
product: 462169
phi: 460800
pubKey: 19
privKey: 145515
Process returned 0 (0x0) execution time : **756.670 s**
Press any key to continue.
我需要这个循环以更快的速度工作。有没有更有效的方法来执行这个动作?
注:我的循环调用另一个函数,isPrime
,这是它的代码,如果有人想要的话。
bool isPrime(int num)
{
bool prime = true;
if(num < 2)
prime = true;
for (int i=2; i<num; i++)
if (num % i == 0)
prime = false;
return prime ;
}
我理解你的问题是,你想找到某个范围[a,b]
中的所有质数。
如果你有足够的内存,最快的方法可能是使用埃拉托色尼筛法。维基百科有一个很好的例子来说明它是如何工作的:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
列表中的第一个数字是2;每隔两个数字就划掉一个它后面的列表从2开始以2为增量进行计数(这些将是列表中2的所有倍数):
2 3 x 5 x 7 x 9 x 11 x 13 x 15 x 17 x 19 x 21 x 23 x 25
2之后的下一个数是3;划掉每一个从3开始,以增量的方式,从它后面的列表中的第三个数开始计数3(这些将是列表中所有3的倍数):
2 3 x 5 x 7 x x x 11 x 13 x x x 17 x 19 x x x 23 x 25
列表中3之后的下一个未划掉的数字是5;从5开始以5为增量(即5的所有倍数),划掉列表中其后每5个数字:
2 3 x 5 x 7 x x x 11 x 13 x x x 17 x 19 x x x 23 x x
这比检查每个数字是否为素数要快,因为外部循环只遍历每个素数,而内部循环运行得越来越快。质数的倒数和是loglogn
,所以总的时间是O(nloglogn)
。
O(n^2)
或O(n^(3/2))
好得多,质数检查更快。在您的例子中,性能下降来自您的原数测试例程。尝试以下作为第一个优化:
bool isPrime(int num)
{
bool prime = true;
if(num < 2)
prime = true;
for (int i = 2; i < (int)sqrt(num) + 1; i++)
if (num % i == 0)
prime = false;
return prime ;
}
您可以在这里找到一些基本素数测试的其他优化步骤:http://en.kioskea.net/faq/977-c-language-checking-whether-an-integer-is-a-prime-number
我建议用埃拉托色尼筛法来解决你的问题。但我也看到或多或少有三种非常简单的优化可以大大提高代码的速度!
for (int i=3; i<=num; i += 2)
if(isPrime(i))
coprimes.push_back(i);
这将跳过每个偶数。我们知道它们不可能是质数。你的速度已经翻倍了!(不完全是几乎)。
下面是两个优化:
bool isPrime(int num)
{
// If your function is only executed from that loop above, delete this statement.
if(num < 2)
return false;
if(!(num % 2))
return num == 2;
int limit = sqrt(num);
for (int i=3; i<=limit; i += 2)
if (!(num % i))
// You can stop after you found the first divisor
return false;
return true;
}
您不需要布尔值,因为除了最后一个return
之外,您从不在任何地方使用它。然后首先要检查它是否能被2整除。如果是这样的话,我们可以结束了。这样就可以跳过所有的偶数因子。接下来取你的数字的平方根来检查。我知道这很耗时,但是对于较大的数字来说是值得的,因为你不需要检查大多数数字。
有了这些小小的优化,你的代码将会快得多。我猜它应该能够在不到100秒的时间内完成(如果你之前的结果超过700)。
要搜索大量的素数,最好使用埃拉托色尼的筛子和维基百科,这是一个很好的开始。从那里我学会了这个算法
看起来您可能经常使用这个程序,那么您为什么不尝试实现Eratosthenes筛并将结果存储在文件中呢?
这不仅需要将找到的素数添加到向量中,还需要将结果写入文件。这样,您可能只需要缓慢地运行它一次,并且将来您可以检查phi是否大于文件中的最后一个数字。如果不是,很好,因为您可以使用文件中的数字。如果是,就从n + 1到开始检查,其中n是文件中的最后一个素数。
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法