利用素数表快速寻找 n 以内的所有素数

本文对比分析了使用素数表方法和传统方法查找指定范围内的素数的效率与实现细节,通过测试不同数据量级的素数计数来评估两种算法的性能。着重展示了算法实现步骤、时间复杂度考量以及实际应用中的优化策略。

http://blog.youkuaiyun.com/wxyztuv/article/details/7965556

三个函数,find_prime() 是利用素数表的方法,寻找素数的,find_prime_stupid()是利用另一种传统方法寻找素数的,test_func()用于测试两个函数的速度

测试数据分别是 1000,5000,10000,50000,100000,500000,1000000,2000000,5000000 以内的素数。


[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <windows.h>  
  4. #include <math.h>  
  5. #include <time.h>  
  6.   
  7. #define SIZE 10000000  
  8.   
  9. void find_prime(int n);  
  10. void find_prime_stupid(int n);  
  11. int test_func(void);  
  12.   
  13. // 建立一个素数表  
  14. int prime[SIZE] = {0};  
  15. int prime_index = 0;        // 素数表索引  
  16.   
  17.   
  18. int main(int argc,char **argv)  
  19. {  
  20.     test_func();  
  21.     return 0;  
  22. }  
  23.   
  24.   
  25. // 速度测试函数  
  26. int test_func(void)  
  27. {  
  28.     time_t start_time,end_time;  
  29.     int test_data[] = {1000,5000,10000,50000,100000,500000,1000000,2000000,5000000,0};  
  30.     int i_testdata = 0;  
  31.       
  32.     printf("\n\nstart testing...\n\n");  
  33.   
  34.     // 测试 find_prime() 函数  
  35.     printf("find_prime():\n");  
  36.     while(test_data[i_testdata])  
  37.     {  
  38.         printf("%d\t\t",test_data[i_testdata]);  
  39.         time(&start_time);  
  40.   
  41.         find_prime(test_data[i_testdata]);  
  42.   
  43.         time(&end_time);  
  44.         printf("%ds\n",end_time - start_time);  
  45.         ++i_testdata;  
  46.   
  47.     }  
  48.   
  49.     // 测试 find_prime_stupid() 函数  
  50.     printf("\n\n");  
  51.     i_testdata = 0;  
  52.     printf("find_prime_stupid():\n");  
  53.     while(test_data[i_testdata])  
  54.     {  
  55.         printf("%d\t\t",test_data[i_testdata]);  
  56.         time(&start_time);  
  57.   
  58.         find_prime_stupid(test_data[i_testdata]);  
  59.   
  60.         time(&end_time);  
  61.         printf("%ds\n",end_time - start_time);  
  62.         ++i_testdata;  
  63.     }  
  64.   
  65.   
  66.     return 0;  
  67. }  
  68.           
  69.   
  70.   
  71. // 若n是合数,则n必有小于或等于n的正平方根(根号n)的一个素因子  
  72. // 遍历当前素数表,如果当前索引的值不为0,  
  73. // 并且值不超过了n的正平方根,并且当前值不能整除i,  
  74. // 则检查素数表的下一个素数  
  75. // 当素数表循环检查停止,检查停止处的索引值,  
  76. // 如果值为0,或者值不能整除i,  
  77. // 则将i加入素数表  
  78.   
  79.   
  80. void find_prime(int n)  
  81. {  
  82.     for(int i = 2; i <= n; ++i)  
  83.     {  
  84.         int j = 0;  
  85.           
  86.         while(prime[j] && i % prime[j] != 0 && prime[j] <= sqrt(i))  
  87.         {  
  88.             ++j;  
  89.         }  
  90.           
  91.         if(!prime[j] || i % prime[j] != 0)  
  92.         {  
  93.             prime[prime_index++] = i;  
  94.            // printf("%d  ",i);  
  95.         }  
  96.     }  
  97. }  
  98.       
  99.   
  100. void find_prime_stupid(int n)  
  101. {  
  102.     int is_prime = 1;  
  103.     for(int i = 2; i <= n; ++i)  
  104.     {  
  105.         for(int j = 2; j <= sqrt(i); ++j)  
  106.         {  
  107.             if(i % j == 0)  
  108.             {  
  109.                 is_prime = 0;  
  110.             }  
  111.         }  
  112.           
  113.         if(is_prime)  
  114.         {  
  115.           //  printf("%d  ",i);  
  116.         }  
  117.         else  
  118.         {  
  119.             is_prime = 1;  
  120.         }  
  121.     }  
  122. }  

### 寻找 N 以内的所有素数 要找到 N 以内的所有素数,可以通过多种方法来实现。以下是几种常见的算法及其 Python 实现。 #### 方法一:暴力枚举法 这种方法通过逐一检查每个数字是否为素数来进行筛选。对于每一个数字 `k`,它会尝试被 `[2, k-1]` 范围内的所有数字整除。如果存在任何能整除它的数字,则说明这个数字不是素数[^4]。 ```python def find_primes_brute_force(n): primes = [] for num in range(2, n + 1): is_prime = True for divisor in range(2, int(num ** 0.5) + 1): # 只需检查到 sqrt(num) if num % divisor == 0: is_prime = False break if is_prime: primes.append(num) return primes ``` #### 方法二:埃拉托斯特尼筛法(Sieve of Eratosthenes) 这是一种高效的查找素数的方法。基本思路是从最小的素数 2 开始,将其所有的倍数标记为合数;接着取下一个未被标记的数字作为新的素数,并重复上述过程直到处理完所有数字[^3]。 ```python def sieve_of_eratosthenes(n): is_prime = [True] * (n + 1) p = 2 while p * p <= n: if is_prime[p]: for multiple in range(p * p, n + 1, p): is_prime[multiple] = False p += 1 primes = [i for i in range(2, n + 1) if is_prime[i]] return primes ``` #### 方法三:优化版埃拉托斯特尼筛法 进一步优化后的版本只考虑奇数部分以及减少不必要的内存占用。此方法利用了观察到的事实——即除了 2 和 3 外的所有素数都可以表示成形如 \(6n \pm 1\) 的形式。 ```python import math def optimized_sieve(n): limit = int(math.sqrt(n)) + 1 flags = [True] * (n + 1) # 设置初始条件 flags[0], flags[1] = False, False # 遍历并消除非素数项 for i in range(2, limit): if flags[i]: start = i * i step = i << 0 # 即步长为 i for j in range(start, n + 1, step): flags[j] = False # 收集剩余标志位中的索引值 result = [index for index, value in enumerate(flags) if value] return result ``` 以上三种方法各有优劣,在实际应用中可以根据具体需求选择合适的方式。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值