对于质数的研究
试除法判断质数
试除法的思想
试除法是一种简单且直观的方法,用来判断一个数是否为质数。它的基本思想是:对于待判断的数 ( n ),从小到大地试除每个小于 ( n ) 的数 ( i ),如果 ( n ) 能被任何 ( i ) 整除且 () 和 (),则 ( n ) 不是质数;否则,( n ) 是质数。
下面是用试除法判断一个数 ( n ) 是否为质数的示例代码:
#include <iostream>
using namespace std;
bool isPrime(int n) {
if (n <= 1) return false; // 小于等于1的数不是质数
if (n == 2) return true; // 2是质数
// 从2开始试除,一直试除到 sqrt(n)
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false; // 如果能整除,则不是质数
}
}
return true; // 如果没有能整除的数,则是质数
}
int main() {
int n;
cout << "Enter a number: ";
cin >> n;
if (isPrime(n)) {
cout << n << " is a prime number." << endl;
} else {
cout << n << " is not a prime number." << endl;
}
return 0;
}
解释:
-
函数
isPrime
:- 首先判断如果 ( n \leq 1 ),则返回
false
,因为质数定义是大于1的正整数。 - 如果 ( n = 2 ),则返回
true
,因为2是质数。 - 接下来,用一个循环从2开始到 ( \sqrt{n} )(因为如果 ( n ) 有大于 ( \sqrt{n} ) 的因子,它的对称因子必然小于 ( \sqrt{n} ))逐个试除。
- 如果能整除任何一个数 ( i ),则返回
false
,表示 ( n ) 不是质数。 - 如果循环结束都没有找到能整除的数,则返回
true
,表示 ( n ) 是质数。
- 首先判断如果 ( n \leq 1 ),则返回
-
主函数
main
:- 从用户输入一个数 ( n ),然后调用
isPrime
函数判断它是否为质数,并输出相应的结果。
- 从用户输入一个数 ( n ),然后调用
总结:
试除法是一种简单但有效的方法来判断一个数是否为质数。它的时间复杂度为 ( O(\sqrt{n}) ),效率较高,尤其适合用于判断单个数是否为质数的场景。
2.埃氏筛法求质数
埃氏筛(Sieve of Eratosthenes)是一种用来找出一定范围内所有素数的经典算法。它由古希腊数学家埃拉托斯特尼斯(Eratosthenes)发明,用于解决寻找素数的问题。
算法原理
埃氏筛的基本思想是:
- 初始化一个布尔类型的数组,称为标记数组(或筛选数组),用来标记每个整数是否为素数。数组的下标表示整数,数组的值为
true
表示该下标对应的整数是素数,为false
表示不是素数。 - 从小到大依次遍历每个整数
i
,若发现i
是素数,则将i
的所有倍数标记为非素数(即将对应位置的布尔值设为false
),除了i
本身。
具体步骤如下:
- 初始化一个布尔数组
is_prime
,将数组中所有元素初始化为true
。 - 将
is_prime[0]
和is_prime[1]
设为false
,因为 0 和 1 不是素数。 - 从
2
开始遍历到sqrt(n)
,对于每个素数i
,将i
的所有倍数(除了i
本身)设为false
。 - 最终,所有值为
true
的下标即为素数。
算法优化
- 减少遍历范围: 在埃氏筛中,我们只需要遍历到
sqrt(n)
就可以了,因为如果i
是n
的因子,那么n/i
也一定是n
的因子。 - 空间优化: 如果要找出的素数范围不是很大,可以优化空间。例如,使用标记数组只标记奇数,可以将空间使用减半。
示例
以找出小于等于 n
的所有素数为例,以下是使用埃氏筛的 C++ 实现示例:
#include <iostream>
#include <vector>
std::vector<int> sieve_of_eratosthenes(int n) {
std::vector<bool> is_prime(n + 1, true); // 默认所有数都是素数
std::vector<int> primes;
is_prime[0] = is_prime[1] = false; // 0和1不是素数
for (int i = 2; i * i <= n; ++i) {
if (is_prime[i]) {
for (int j = i * i; j <= n; j += i) {
is_prime[j] = false; // 将i的倍数标记为非素数
}
}
}
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) {
primes.push_back(i); // 收集所有素数
}
}
return primes;
}
int main() {
int n = 30; // 找出小于等于30的所有素数
std::vector<int> primes = sieve_of_eratosthenes(n);
std::cout << "Prime numbers less than or equal to " << n << " are:\n";
for (int prime : primes) {
std::cout << prime << " ";
}
std::cout << std::endl;
return 0;
}
在这个示例中,sieve_of_eratosthenes
函数返回小于等于 n
的所有素数的列表。程序首先初始化一个标记数组 is_prime
,然后根据埃氏筛的算法进行标记,最后收集所有值为 true
的下标作为素数输出。
埃氏筛是一种高效的算法,时间复杂度为 O(n log log n),适用于寻找较小范围内的素数集合。