您好,登录后才能下订单哦!
# 怎么用C语言求素数(大于1只能被1跟本身除的数)
## 一、素数的定义与数学原理
素数(Prime number)是指在大于1的自然数中,除了1和它本身以外,不能被其他自然数整除的数。例如:2、3、5、7、11等都是素数,而4、6、8、9等则不是素数(称为合数)。
### 1.1 素数的基本性质
- 大于1的正整数
- 只有1和自身两个正约数
- 2是唯一的偶素数
- 素数的个数是无限的(欧几里得证明)
### 1.2 素数的数学意义
素数在数论中占有重要地位,被称为"数学的原子"。现代密码学(如RSA算法)和大数分解等许多领域都依赖于素数的性质。
## 二、判断素数的基本方法
### 2.1 暴力法(试除法)
最直观的方法是试除法:对于一个数n,检查从2到n-1的所有整数是否能整除n。
```c
#include <stdio.h>
#include <stdbool.h>
bool isPrime_brute(int n) {
if (n <= 1) return false;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
时间复杂度:O(n)
实际上,我们只需要检查到√n即可,因为如果n有大于√n的因数,那么它必然对应一个小于√n的因数。
#include <math.h>
bool isPrime_optimized(int n) {
if (n <= 1) return false;
int limit = sqrt(n);
for (int i = 2; i <= limit; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
时间复杂度:O(√n)
适用于批量找出一定范围内的所有素数。
算法步骤: 1. 初始化一个布尔数组,标记所有数为素数 2. 从2开始,将所有倍数标记为非素数 3. 重复直到√n
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void sieveOfEratosthenes(int n) {
bool *prime = (bool *)malloc((n+1)*sizeof(bool));
memset(prime, true, (n+1)*sizeof(bool));
prime[0] = prime[1] = false;
for (int p = 2; p*p <= n; p++) {
if (prime[p]) {
for (int i = p*p; i <= n; i += p) {
prime[i] = false;
}
}
}
// 输出素数
for (int p = 2; p <= n; p++) {
if (prime[p]) {
printf("%d ", p);
}
}
free(prime);
}
时间复杂度:O(n log log n)
更高效的筛法,每个合数只被标记一次。
void eulerSieve(int n) {
bool *isPrime = (bool *)malloc((n+1)*sizeof(bool));
int *primes = (int *)malloc(n*sizeof(int));
int count = 0;
memset(isPrime, true, (n+1)*sizeof(bool));
isPrime[0] = isPrime[1] = false;
for (int i = 2; i <= n; i++) {
if (isPrime[i]) {
primes[count++] = i;
}
for (int j = 0; j < count && i*primes[j] <= n; j++) {
isPrime[i*primes[j]] = false;
if (i % primes[j] == 0) break;
}
}
// 输出结果
for (int i = 0; i < count; i++) {
printf("%d ", primes[i]);
}
free(isPrime);
free(primes);
}
时间复杂度:O(n)
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main() {
printf("100以内的素数:\n");
for (int i = 2; i <= 100; i++) {
bool isPrime = true;
for (int j = 2; j <= sqrt(i); j++) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
printf("%d ", i);
}
}
return 0;
}
验证大于2的偶数可以表示为两个素数之和。
bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i*i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
void goldbachConjecture(int even) {
if (even <= 2 || even % 2 != 0) {
printf("输入必须大于2的偶数\n");
return;
}
for (int i = 2; i <= even/2; i++) {
if (isPrime(i) && isPrime(even - i)) {
printf("%d = %d + %d\n", even, i, even - i);
return;
}
}
printf("哥德巴赫猜想不成立!\n");
}
对于需要频繁判断素数的应用,可以预先计算并存储素数表。
可以用位操作来压缩存储空间,每个比特位表示一个数的素性。
#define SET_BIT(arr, x) (arr[x/8] |= (1<<(x%8)))
#define GET_BIT(arr, x) (arr[x/8] & (1<<(x%8)))
void bitwiseSieve(int n) {
int size = (n/8) + 1;
unsigned char *prime = (unsigned char *)malloc(size);
memset(prime, 0xFF, size);
// 0和1不是素数
SET_BIT(prime, 0);
SET_BIT(prime, 1);
for (int p = 2; p*p <= n; p++) {
if (GET_BIT(prime, p)) {
for (int i = p*p; i <= n; i += p) {
SET_BIT(prime, i);
}
}
}
// 输出素数
for (int i = 2; i <= n; i++) {
if (GET_BIT(prime, i)) {
printf("%d ", i);
}
}
free(prime);
}
对于超大范围的素数计算,可以使用多线程并行处理不同区间的数。
概率性素数测试算法,适用于大数判断。
#include <stdlib.h>
#include <time.h>
long long power(long long a, long long d, long long n) {
long long result = 1;
a = a % n;
while (d > 0) {
if (d & 1) result = (result * a) % n;
d >>= 1;
a = (a * a) % n;
}
return result;
}
bool millerTest(long long d, long long n) {
long long a = 2 + rand() % (n - 4);
long long x = power(a, d, n);
if (x == 1 || x == n-1) return true;
while (d != n-1) {
x = (x * x) % n;
d *= 2;
if (x == 1) return false;
if (x == n-1) return true;
}
return false;
}
bool isPrime_miller(long long n, int k) {
if (n <= 1 || n == 4) return false;
if (n <= 3) return true;
long long d = n - 1;
while (d % 2 == 0) d /= 2;
for (int i = 0; i < k; i++) {
if (!millerTest(d, n)) {
return false;
}
}
return true;
}
简要介绍RSA算法如何利用大素数实现加密。
本文详细介绍了在C语言中判断和生成素数的多种方法,从最基础的试除法到高效的筛法,再到高级的概率测试算法。理解这些算法不仅能提高编程能力,还能深入理解数论的基础知识。
关键点回顾: 1. 素数判断的核心是试除,但需要优化范围 2. 筛法适合批量生成素数 3. 不同场景需要选择不同算法 4. 注意边界条件和性能优化
通过实践这些代码,读者可以掌握素数相关的编程技巧,为进一步学习算法和数论打下坚实基础。
附录:完整示例代码
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// 函数声明
bool isPrime_brute(int n);
bool isPrime_optimized(int n);
void sieveOfEratosthenes(int n);
void eulerSieve(int n);
void goldbachConjecture(int even);
void bitwiseSieve(int n);
bool isPrime_miller(long long n, int k);
int main() {
// 测试各个函数
printf("暴力法判断17是否为素数: %s\n",
isPrime_brute(17) ? "是" : "否");
printf("优化法判断17是否为素数: %s\n",
isPrime_optimized(17) ? "是" : "否");
printf("\n埃拉托斯特尼筛法(100以内素数):\n");
sieveOfEratosthenes(100);
printf("\n\n欧拉筛法(100以内素数):\n");
eulerSieve(100);
printf("\n\n哥德巴赫猜想验证(20):\n");
goldbachConjecture(20);
printf("\n位运算筛法(50以内素数):\n");
bitwiseSieve(50);
printf("\n\n米勒-拉宾测试(判断1000003是否为素数): %s\n",
isPrime_miller(1000003, 5) ? "可能是" : "不是");
return 0;
}
// 各函数实现(前文已给出,此处省略)
参考资料: 1. 《算法导论》 - Thomas H. Cormen 2. 《数论导引》 - G.H. Hardy 3. C标准库文档 4. 相关数学论文和在线资源 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。