码迷,mamicode.com
首页 > 编程语言 > 详细

素数序列的生成及其应用(采用了自研的高效算法)

时间:2018-04-19 00:33:31      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:string   结果   png   正整数   否则   初始   ora   loop   math   

问题:

  • 2000以内的素数有哪些?
  • 她的手机号是素数吗?

思路:

问题归类:

  • 怎样获取n以内的所有素数呢?
  • 怎样高效地判定一个正整数是否为素数呢?

假设已知:

第一个素数是2,第二个素数是3;

断定某正整数n确实为素数的依据是:当且仅当 若不超过n的算数平方根的所有素数都不能整除n,那么就断定n为素数

酝酿策略:

先解决“获取n以内的所有素数”的问题,然后应用其结果来解决“高效地判定一个正整数是否为素数”的问题。

从第三个待定素数开始,以后总是把下一个候选素数的初始值取为当前已知的最后一个素数(必为奇数)
然后执行下述循环
LOOP
把该待定素数(为奇数)的值更新为其下一个奇数的值:prime_number_candidate += 2;
探测该待定素数是否确实为素数:若是,则把它作为正式的素数写到素数数组中下一个素数的位置上;否则,直接去继续下一轮循环。

END LOOP

代码实践:

头文件:prime_number.h

 1 #pragma once
 2 
 3 /*制定 素数数组的元素以及计数下标的数据类型*/
 4 typedef unsigned long long PRIME_INTEGER_TYPE, PRIME_INTEGER_ARRAY_COUNT_TYPE;
 5 
 6 /*制定 容量可动态调整的素数数组容器数据类型*/
 7 typedef struct {
 8     PRIME_INTEGER_TYPE *prime_integer_array; // 容量可动态调整的素数数组
 9     PRIME_INTEGER_ARRAY_COUNT_TYPE count; // 素数数组中元素的数目
10 }PRIME_INTEGER_ARRAY_TYPE;
11 
12 /************************************全局常量的声明************************************/
13 extern PRIME_INTEGER_ARRAY_TYPE EMPTY_PRIME_INTEGER_ARRAY;
14 extern char *PRIME_INTEGER_TYPE_PRINT_FORMAT_STRING, *PRIME_INTEGER_ARRAY_COUNT_TYPE_PRINT_FORMAT_STRING;
15 
16 /*获取upper_limit以内的素数数组*/
17 PRIME_INTEGER_ARRAY_TYPE getPrimeIntegerArrayBelow(PRIME_INTEGER_TYPE upper_limit);
18 
19 /*格式化地打印upper_limit以内的全部素数*/
20 void printPrimeIntegerArrayBelow(PRIME_INTEGER_TYPE upper_limit);
21 
22 /*判断一个给定的数是否为素数*/
23 int isPrimeInteger(PRIME_INTEGER_TYPE n);

 

源文件:prime_number.c

  1 #include "prime_number.h"
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <math.h>
  5 
  6 /************************************全局常量的定义************************************/
  7 PRIME_INTEGER_ARRAY_TYPE EMPTY_PRIME_INTEGER_ARRAY = {NULL, 0}; // 空素数数组
  8 char *PRIME_INTEGER_TYPE_PRINT_FORMAT_STRING = "%2llu", *PRIME_INTEGER_ARRAY_COUNT_TYPE_PRINT_FORMAT_STRING = "%2llu"; // 设置打印素数数组时元素及下标的输出格式符
  9 
 10 /**************************************方法的定义**************************************/
 11 
 12 /*获取upper_limit以内的素数数组*/
 13 PRIME_INTEGER_ARRAY_TYPE getPrimeIntegerArrayBelow(PRIME_INTEGER_TYPE upper_limit) {
 14     /*最小的素数为2,因此在2之前的素数数组为空素数数组*/
 15     if (upper_limit < 2) {
 16         return EMPTY_PRIME_INTEGER_ARRAY;
 17     }
 18     /*在upper_limit以内顶多有max_count个素数,*/
 19     PRIME_INTEGER_ARRAY_COUNT_TYPE max_count = (upper_limit + 1) / 2;
 20     /*开辟足够的空间用来容纳upper_limit以内的全部素数*/
 21     PRIME_INTEGER_TYPE *prime_integer_array = (PRIME_INTEGER_TYPE *)malloc((size_t)(max_count) * sizeof(PRIME_INTEGER_TYPE));
 22     /*装载第一个素数*/
 23     prime_integer_array[0] = 2;
 24     if (upper_limit == 2) {
 25         return (PRIME_INTEGER_ARRAY_TYPE) { prime_integer_array, 1 };
 26     }
 27     /*装载第二个素数*/
 28     prime_integer_array[1] = 3;
 29     if (upper_limit <= 4) {
 30         return (PRIME_INTEGER_ARRAY_TYPE) { prime_integer_array, 2 };
 31     }
 32     /*后续素数均通过算法来求取*/
 33     PRIME_INTEGER_ARRAY_COUNT_TYPE i = 1; // 接下来会用作while循环的步进变量
 34     PRIME_INTEGER_TYPE next_prime_integer_candidate = prime_integer_array[i], prober_upper_limit;
 35     int flag = 1; // 接下来会把flag当作布尔变量来用
 36     PRIME_INTEGER_ARRAY_COUNT_TYPE j; // 接下来会用作内部for循环的步进变量
 37     while (i < max_count) {
 38         /*把下一个奇数作为下一个素数候选者*/
 39         next_prime_integer_candidate += 2;
 40         /*仅装载upper_limit以内的全部素数,若已装载完毕就退出循环*/
 41         if (next_prime_integer_candidate > upper_limit) {
 42             break;
 43         }
 44         /*取下一个素数候选者的算术平方根的去尾近似值作为用来探测下一个素数候选者是否确实为素数的探测者的上限*/
 45         prober_upper_limit = llroundl(sqrtl(next_prime_integer_candidate*1.0));
 46         /*从第二个素数开始,依次用prober_upper_limit以内的素数来探测下一个素数候选者是否确实为素数*/
 47         for (j = 1;
 48             (j <= i)
 49             &&
 50             /*只需用prober_upper_limit以内的素数来探测*/
 51             (flag = prime_integer_array[j] <= prober_upper_limit)
 52             && 
 53             /*当且仅当prober_upper_limit以内的所有素数都不能整除下一个素数候选者时,才断定下一个素数候选者确实为素数*/
 54             (next_prime_integer_candidate % prime_integer_array[j] != 0);
 55             ++j)
 56         ;
 57         /* 退出上面的for循环的原因有两种:
 58         ** (1)prober_upper_limit以内的素数都已经作为探测者使用过了也没能否认下一个素数候选者
 59         ** (2)下一个素数候选者被prober_upper_limit以内的某个素数整除了*/
 60         /*若是因为原因(1)而退出上面的for循环,那么就可断定下一个素数候选者确实为素数*/
 61         if (flag == 0) {
 62             /*把下一个素数候选者正式作为下一个素数写入素数数组的下一个位置中*/
 63             prime_integer_array[++i] = next_prime_integer_candidate;
 64             /*最终i的值也就是prime_integer_array的最大有效下标*/
 65         }        
 66     }
 67     /*现在已经知到了prime_integer_array中确切的素数个数,那么就把它所占的空间收缩到恰到好处的大小吧*/
 68     prime_integer_array = (PRIME_INTEGER_TYPE *)realloc(prime_integer_array, (size_t)(i + 1)* sizeof(PRIME_INTEGER_TYPE));
 69     return (PRIME_INTEGER_ARRAY_TYPE) { prime_integer_array, i + 1 };
 70 }
 71 
 72 /*格式化地打印upper_limit以内的全部素数*/
 73 void printPrimeIntegerArrayBelow(PRIME_INTEGER_TYPE upper_limit) {
 74     PRIME_INTEGER_ARRAY_TYPE pia = getPrimeIntegerArrayBelow(upper_limit);
 75     if (pia.count == 0) {
 76         printf("EMPTY_PRIME_INTEGER_ARRAY\n");
 77     }
 78     else {
 79         PRIME_INTEGER_ARRAY_COUNT_TYPE i = 0;
 80         while (i < pia.count) {
 81             printf("PrimeIntegerArray(");
 82             printf(PRIME_INTEGER_ARRAY_COUNT_TYPE_PRINT_FORMAT_STRING, i);
 83             printf(") = ");
 84             printf(PRIME_INTEGER_TYPE_PRINT_FORMAT_STRING, pia.prime_integer_array[i]);
 85             printf("\n");
 86             ++i;
 87         }
 88     }
 89 }
 90 
 91 /*
 92 **判断一个给定的数是否为素数
 93 **思路:当且仅当 若不超过其算数平方根的所有素数都不能整除n,那么断定n为素数;
 94 */
 95 int isPrimeInteger(PRIME_INTEGER_TYPE n) {
 96     if (n < 2) {
 97         return 0;
 98     }
 99     if (n == 2 || n == 3 || n == 5 || n == 7) {
100         return 1;
101     }
102     if (n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0) {
103         return 0;
104     }
105     /*取下一个素数候选者的算术平方根的去尾近似值作为用来探测下一个素数候选者是否确实为素数的探测者的上限*/
106     PRIME_INTEGER_TYPE prober_upper_limit = llroundl(sqrtl(n*1.0));
107     /*生成探测者的上限以内的素数数组*/
108     PRIME_INTEGER_ARRAY_TYPE pia = getPrimeIntegerArrayBelow(prober_upper_limit);
109     /*在上面的if语句中,2, 3, 5, 7这前4个素数已经用过了,下面直接从素数数组中第五个(其下标为4)的那个素数开始作为探测者*/
110     PRIME_INTEGER_ARRAY_COUNT_TYPE i = 4;
111     while (i < pia.count) {
112         /*一旦被素数数组中的某素数否认,则直接返回“假”(这里用0表示“假”,用1表示“真”)*/
113         if (n % pia.prime_integer_array[i] == 0) {
114             return 0;
115         }
116         ++i;
117     }
118     /*程序能执行到这一行,就能肯定n确实为素数。因为如果n不是素数,那么在上面的while循环中就已经直接return退出了*/
119     return 1;
120 }

 

源文件:main.c

1 #include "prime_number.h"
2 #include <stdio.h>
3 
4 int main(int argc, char **argv) {
5     printPrimeIntegerArrayBelow(100);
6     
7     printf("isPrimeInteger(97) = %d\n", isPrimeInteger(97));
8     return 0;
9 }

 

运行展示:

技术分享图片

 

素数序列的生成及其应用(采用了自研的高效算法)

标签:string   结果   png   正整数   否则   初始   ora   loop   math   

原文地址:https://www.cnblogs.com/yawenunion/p/8878576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!