求解素数几种方法

【C语言】求素数的三种方案 【C语言】求素数的三种方法 阅读详情
转贴文章请注明:逸学堂
 
求解一个算法,我们首先要知道它的数学含义.依据这个原则,首先我们要知道什么是素数.; 素数是这样的整数,它除了表示为它自己和1的乘积以外,无论他表示为任何两个整数的乘积。
找素数的方法多种多样。
1:是从2开始用“是则留下,不是则去掉”的方法把所有的数列出来(一直列到你不想再往下列为止,比方说,一直列到10,000)。第一个数是2,它是一个素数,所以应当把它留下来,然后继续往下数,每隔一个数删去一个数,这样就能把所有能被2整除、因而不是素数的数都去掉。在留下的最小的数当中,排在2后面的是3,这是第二个素数,因此应该把它留下,然后从它开始往后数,每隔两个数删去一个,这样就能把所有能被3整除的数全都去掉。下一个未去掉的数是5,然后往后每隔4个数删去一个,以除去所有能被5整除的数。再下一个数是7,往后每隔6个数删去一个;再下一个数是11,往后每隔10个数删一个;再下一个是13,往后每隔12个数删一个。就这样依法做下去。
但是编程我们一般不采用上面的方法,并不说这中方法计算机实现不了,或者说实现算法比较复杂。因为它更像一个数学推理。最后我们也给一个算法。
下面我们介绍几种长用的编程方法。
       2: 遍历2以上N的平方根以下的每一个整数,是不是能整除N ;( 这是最基本的方法)
       3 :遍历2以上N的平方根以下的每一个素数,是不是能整除N ;( 这个方法是上面方法的改进,但要求 N 平方根以下的素数已全部知道 )
       4
:采用 Rabin-Miller 算法进行验算;
例如:N = 2 ^ 127 - 1是一个38位数,要验证它是否为素数,用上面几个不同的方法:
验算结果,假设计算机能每秒钟计算1亿次除法,那么
算法 2 要用4136年,算法 3 要用93年,算法 4 只要不到1秒钟! ( 这些数据是通过计算得到 )
 
另外印度有人宣称素数测试是 P 问题,我一直没有找到那篇论文,听说里面有很多数学理论。如果那位大人有这篇论文,麻烦转发一份( E-Mail:exuetang@126.com )有任何问题也可以写信与我讨论。
 
下面我们分别实现上面的三种算法:
以下算法我们不涉及内存溢出,以及大数字的问题。如果测试数字超过2^32,发生内存溢出,你需要自己使用策略解决这个问题,在这里只讨论32位机有效数字算法。
1 : // 算法0:是从2开始用“是则留下,不是则去掉”的方法把所有的数列出来
// 最后数组中不为0的数字就是要查找的素数。
void PrimeNumber0()
{
     //   int time ::GetTickCount();
     //   cout << "start time:" << time << endl;
 
     int Max[MAX_NUMBER];        // 在栈上分配,栈上空间要求一般都在2M之间,
     //   如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).
     memset(Max,0,MAX_NUMBER);
     for(int i = 0 ; i < MAX_NUMBER; ++i)
     {
          Max[i] = i;
     }
     int cout = 0;// 记录当前i的位置
 
     // 遍历整个数组
     for(i = 1; i < MAX_NUMBER; ++i)
     {
         if(Max[i] != 0 )// 如果数据不为0,说明是一个素数
         {
              int iCout = i;
              int j = Max[i];// 记录数组中数组位的数字,以便设置
              while((iCout+=j) < MAX_NUMBER)
              {
                   // 把不是素数的数位在数组中置为0
                   Max[iCout] = 0;
              }
              ++cout;
         }
     }
 
     //   int time ::GetTickCount();
     //   cout << "end time:" << time << endl;
}
 
2 :这个算法可以修改成为,验证一个给定数字是否是一个素数。
// 因为我们讨论多个算法,所以我们把每个算法都单独
// 写在一个或多个函数内。这些函数并不要求输入值和返回值
// 如果你需要这些结果,可以自己修改。
 
// 算法1:遍历2以上N的平方根以下的每一个整数,是不是能整除N;
void PrimeNumber1()
{
//   int time ::GetTickCount();
//   cout << "start time:" << time << endl;
 
     int Max[MAX_NUMBER/2];      // 在栈上分配,栈上空间要求一般都在2M之间,
//   如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
// 所以没有必要申请和所求数字同样大小的空间。
     memset(Max,0,MAX_NUMBER);
     Max[0] = 2;// 放入第一个素数,有人说2不是素数,如果你是其中一员,就改成3吧
     int cout = 1;// 记录素数个数
 
     // 挨个数进行验证
     bool bflag = true;
     for(int i = 3; i < MAX_NUMBER; ++i)
     {
         bflag = true;
         // 需要是使用数学库(math.h)中sqrt
         int iTemp = (int)sqrt((float)i);// 强制转换成int类型,有的人在这里使用i+1就是为了增加sqrt的精度
         // 没有特殊函数,你也可以使用int iTemp = (int)sqrt(i)+1;来提高进度
         for (int j = 2; j < iTemp; ++j)
         {
              if(i%j == 0)// 求余,如果为0说明,可以整除,不是素数。
              {
                   bflag = false;
                   break;
              }
         }
         // 经过验证是素数,放入数组。
         if(bflag)
         {
              Max[cout++] = i;
         }
     }
 
//   int time ::GetTickCount();
//   cout << "end time:" << time << endl;
 
}
 
3 :这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道
// 算法2:遍历2以上N的平方根以下的每一个素数,是不是能整除N;
// ( 这个方法是上面方法的改进,但要求N平方根以下的素数已全部知道)
void PrimeNumber2()
{
     //   int time ::GetTickCount();
     //   cout << "start time:" << time << endl;
 
     int Max[MAX_NUMBER/2];      // 在栈上分配,栈上空间要求一般都在2M之间,
     //   如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
     // 所以没有必要申请和所求数字同样大小的空间。
     memset(Max,0,MAX_NUMBER);
     Max[0] = 2;// 放入第一个素数,有人说2不是素数,如果你是其中一员,就改成3吧
     int cout = 1;// 记录素数个数
 
     // 挨个数进行验证
     bool bflag = true;
     for(int i = 3; i < MAX_NUMBER; ++i)
     {
         bflag = true;
         // 需要是使用数学库(math.h)中sqrt
         int iTemp = (int)sqrt((float)i);// 强制转换成int类型,有的人在这里使用i+1就是为了增加sqrt的精度
         // 没有特殊函数,你也可以使用int iTemp = (int)sqrt(i)+1;来提高进度
/////////////////////////////////////////////////////////////////////////////////
         // 修改的是这里以下的部分
         for (int j = 0; j < cout; ++j)
         {
              if(i%Max[j] == 0)// 求余,如果为0说明,可以整除,不是素数。
              {
                   bflag = false;
                   break;
              }
         }
         // 修改的是这里以上的部分
//////////////////////////////////////////////////////////////////////////////////
         // 经过验证是素数,放入数组。
         if(bflag)
         {
              Max[cout++] = i;
         }
     }
 
     //   int time ::GetTickCount();
     //   cout << "end time:" << time << endl;
 
}
 
4 : 采用 Rabin-Miller 算法进行验算, Rabin-Miller 算法是典型的验证一个数字是否为素数的方法。判断素数的方法是Rabin-Miller概率测试,那么他具体的流程是什么呢。假设我们要判断n是不是素数,首先我们必须保证n 是个奇数,那么我们就可以把n 表示为 n = (2^r)*s+1,注意s 也必须是一个奇数。然后我们就要选择一个随机的整数a (1<=a<=n-1),接下来我们就是要判断 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),如果任意一式成立,我们就说n通过了测试,但是有可能不是素数也能通过测试。所以我们通常要做多次这样的测试,以确保我们得到的是一个素数。(DDS的标准是要经过50次测试)
 
// 算法3:采用Rabin-Miller算法进行验算
// 首先选择一个代测的随机数p,计算b,b是2整除p-1的次数。然后计算m,使得n=1+(2^b)m。
 
// (1) 选择一个小于p的随机数a。
// (2) 设j=0且z=a^m mod p
// (3) 如果z=1或z=p-1,那麽p通过测试,可能使素数
// (4) 如果j>0且z=1, 那麽p不是素数
// (5) 设j=j+1。如果j<b且z<>p-1,设z=z^2 mod p,然后回到(4)。如果z=p-1,那麽p通过测试,可能为素数。
// (6) 如果j=b 且z<>p-1,不是素数
 
// 判定是否存在 a^s=1 (mod n) 或a^((2^j)*s)= -1(mod n)(0<=j<R),
 
bool Witness(int a,int n)
{
     // 解释一下数学词汇:
     // ceil 求不小于x的最小整数,函数原型extern float ceil(float x);求得i的最大值
     // log 计算x的自然对数,函数原型extern float log(float x);
     long i,d=1,x;
     for (i=(int)ceil(log((double)n-1)/log(2.0))-1;i>=0;--i)
     {
         x=d;
         d=(d*d)%n;
         if ((1==d) && (x!=1) && (x!=n-1))
         {
              return 1;
         }
         if ((n-1)&(1<0))
         {
              d=(d*a)%n;
         }
     }
     return (d!=1);
 
}
 
// 参数n,是要测定的数字,s是要内部测试的次数。
bool Rabin_Miller(int n,int s)
{
     for (int j = 0;j < s; ++j)
     {
          int a = rand()*(n-2)/RAND_MAX + 1;// 获得一个随机数1<=a<=n-1
         if (Witness(a,n))// 利用这个随即数和n进行判断对比,只要有一次返回true,就说明n不是一个素数
         {
              return false;
         }
     }
     return true;// 通过验证是一个素数
}
 
// 算法3:采用Rabin-Miller算法进行验算
// 这个算法是求大素数使用的。所以你的必须想办法支持大数字运算,
// 不然极易造成内存访问失效,我在我的机子上,MAX_NUMBER=10000时就会出现问题,1000就没有问题
void PrimeNumber3()
{
    
     int Max[MAX_NUMBER/2];// 在栈上分配,栈上空间要求一般都在2M之间,
     //   如果你需要更大空间,请在堆上申请空间(就是通过malloc,new来申请).素数的个数很少
     // 所以没有必要申请和所求数字同样大小的空间。
     int cout = 0;// 记录素数个数
     memset(Max,0,MAX_NUMBER/2);
 
     for(int i = 2; i < 1000; ++i)
     {
         if(Rabin_Miller(i,20))
         {
              Max[cout++] = i;
         }
     }
}
 
以上程序都经过测试,测试环境Window 2003+VC7.1
小结:以上只是简单介绍一下求素数的几种常用方法,实际方法远远不知这些。对于普通用户来说算法2就可以方便应用了。Rabin-miller算法,确实很高效,但是如果你对数学,编程知识不是很熟悉,建议不要使用。
如果使用过程中有任何疑问请与我联系。
QQ :35091551
素数的求解方法: 一、朴素判断素数算法 就判断素数而言,事实上是非常简单的了。根据定义,判断一个整数n是否是素数,只需要去判断在整数区间[2, n-1]之内,是否具有某个数m,使得n % m == 0。代码可以这么写 阅读详情

相关推荐

ESP32-S3驱动雨滴传感器实战:从原理到ADC/GPIO双模式数据采集

本文详细介绍了ESP32-S3驱动雨滴传感器的实战教程,涵盖其工作原理及ADC/GPIO双模式数据采集方法。通过解析传感器利用水的导电性检测雨量的核心机制,提供了完整的硬件连接方案与软件驱动代码,包括模拟量(AO)的ADC读取和数字量(DO)的GPIO读取,并附有调试技巧,帮助开发者快速实现雨滴检测功能。

weixin_32005771的博客 154

超完整素数算法总结归纳

目录 素数的判定 Eratosthenes筛选(素数筛选) 因子数与因子和 完美数 n的第k个因子 分拆质数和 分解质因数 最接近的因数 丑数 素数的判定 Eratosthenes筛选(素数筛选) 因子数与因子和 完美数 n的第k个因子 分拆质数和 分解质因数 四因数 最接近的因数 丑数 素数的判定 素数的概念是只可以被1和他本身可以整除 所以我们可以使用试除法,如一个数为n (用2-n-1)对n进行试除,但是这样的话时间复杂度是O(N) #...

m0_61567378的博客 3576

科大讯飞(1): 环形6麦语音唤醒—驱动板上的接口

介绍环形麦阵列驱动板上的接口,及其疑问

bing_feilong的博客 1175

素数求法的四种方法(逐次优化)

/* 思路: 素数:即质数,除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下 */ //方法一:试除法 int main() { int i = 0; int count = 0; // 外层循环用来获取100~200之间的所有数据,100肯定不是素数,因此i从101开始 for(i=101; i<=200; i++) { //判断i是否为素数:用[2, i)之间的每个数据去被i除,只要有一个可以被整除,则不是素数 int j = 0; fo

zjybp的博客 5546

AI赋能软件测试:从冒烟测试到全流程智能化的效率革命

软件测试是确保软件质量的关键环节,其核心原理是通过预设用例验证系统功能是否符合预期。传统测试方法依赖人工编写和维护脚本,面临维护成本高、适应性差等挑战。随着人工智能技术的发展,特别是自然语言处理和计算机视觉的成熟,AI为测试领域带来了新的技术价值。通过让AI理解应用界面和业务逻辑,可以实现测试用例的智能生成、自主执行和结果分析,显著提升测试效率和覆盖率。在实际应用场景中,AI驱动的冒烟测试能够动态适应UI变化,自动分析失败日志,将测试人员从重复劳动中解放出来,专注于更复杂的质量策略设计。本文基于AI在冒烟测

weixin_28841265的博客 306

深入解析Panfrost驱动:Mali-GPU开源驱动的架构与实现

本文深入解析了Panfrost驱动作为Mali-GPU开源驱动的架构与实现。从诞生背景到硬件架构演进,详细介绍了Panfrost如何突破ARM闭源策略,实现全栈支持。文章还探讨了驱动设计中的关键技术挑战与性能优化策略,为开发者提供了实用的编译部署指南和性能调优方法。

weixin_30790841的博客 551

【数论】求素数的三种方法

求素数的三种方法:试除法、埃氏筛法、欧拉筛法

Wmiracle的博客 2万+

kali破解wifi之airmon-ng 工具利用

......

qq_42378173的博客 1万+

素数求解的的几种简单方法

问题:打印出100到200之间的素数方法一:素数N就是除了1和它本身之外没有任何因子的数,所以要求素数我们很容易想到从2到N-1去试除,如果能除尽说明它不是素数,这个时候就接着判断下一个数也就是下面的这种 上结果图方法二:方法一是可以做出来,但是要试的因子太多了有点。我们可以想到如果N有除了它本身之外的因子,那这个因子一定小于等于N/2(1*N=N,2*(N/2)=N,一个因子如果比N/2大了,那...

qq_35496396的博客 2万+

十.镜头知识之畸变问题

对于理想光学系统,在一对共轭的物像平面上,像的放大率是一个常数。但是对于实际的光学系统,当视场较大或很大时,像的放大率就要随视场而异,这样就会使像相对于物体失去相似性。这种使像变形的成像缺陷称为畸变。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 2123

斯坦福大学3D点云模型下载

本文整理了斯坦福大学10个经典的点云(pcd)及其模型(ply),方便日后使用,欢迎免费下载!

孙悟空 7733

求解素数的几种方法

试除法 试除法是求解素数最基础的算法,就是用除了1和它本身以外的所有数字一个一个去除要判断的数字,如果余数为0,那么这个数字便不是素数。举例说明: 打印100-200之间的素数 方法一: 采用试除法,结合两层循环,外层循环控制100~200循环次数,内层循环从2到 i-1一个一个去除,如果i%j余数为0,说明该数字有除了1和它本身以外的因数,终止循环,说明没有找到素数。而如果内层循环结束依然没有找...

Nan_Feng726的博客 698

鸿蒙开发实战项目(九十二):HUAWEI Health血压测量

是华为开发的用于运动健康领域的一个开放平台, 三方APP可以借助HUAWEI Health开放平台提供的。

斌擎科技 1131

关于java实现的求素数的几种方法

经过一番艰难的思想斗争,觉得自己并不想学习网络,怀疑自己入错了坑!我想了很久想的我头晕目眩,想的我茶不思,饭不想;想的我不想再想; 走路在想,上课在想,下课在想,睡觉在想,就连拉屎也不得不想,,最后还是决定学习Android开发,不管我的选择是否正确,何况本就没有正确一说,正确与错都只是那些成功者对我们诉说的故事而已!至少我现在不后悔,现在不会以后也不会,因为这就是我的选择; 而且

当然,我在扯淡!(Paulo Airfald) 2万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

素数求解的N种境界

素数即质数,指一个大于1的自然数,除了1和它本身外,不能被其他自然数(质数)整除。通俗来说就是这个数除了1和它自身外再也没有其他因数。例如2,3,5,7等都是素数,它们除了1和本身外再无其他因子。2是最小的质数。1既不是质数也不是合数。合数是与质数相对的数,合数是指除了1和它本身外还有其他因数的数。例如2,4,6,8等皆是合数。素数的求解方法有很多,有句俗话叫做活到老学到老,如何让你的代码让人感觉眼前一亮,学习更多的求解方法肯定是重中之重。它会让你的代码看起来更鲜活,更生动,最重要的是能让你又前进一步。

2201_75806908的博客 4148

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

c语言经典习题之素数的求解

这一篇文章我们讲解素数的求解方法 目录 素数试除法 素数试除法改编提高效率 素数筛选法 素数试除法 题目名称:打印素数 题目内容:写一个代码:打印100~200之间的素数 素数试除法:给定一个合数n(这里,n是待分解的整数),试除法看成是用小于等于n的每个素数去试除待分解的整数。如果找到一个数能够整除除尽,这个数就是待分解整数的因子。试除法一定能够找到n的因子。因为它检查n的所有可能的因子,所以如果这个算法“失败”,也就证明了n是个素数。 通俗的讲就是一个数将 2-数的本身-1 .

欢迎来到我的博客,在这里我会用我的方式来讲解知识,请大家多多关照 355

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【C语言】求解素数(质数)的N种境界

★前言: 众所周知,不管是在学习、考试还是以后找工作中,对于求解素数的问题随处可见,而且还是一个重难点,为何要说是重难点呢?主要是因为对于不同的人往往会有不同做法,但大多数掌握的都是一些非常平庸的做法,完全没有技术含量。然而这对于我们这些技术人员无疑是一个BIG BUG。所以小编在此整理了一些求解套路,如有疑问,欢迎来扰。 ★试除法: 首先要介绍的,当然非"试除法"莫属啦。考...

码农印象 3458

求素数的几种方法

MzForm  

blueness027的专栏 1082

[软工课程博客] 求解第N个素数

任务 求解第 10,0000、100,0000、1000,0000 ... 个素数(要求精确解)。 想法 Sieve of Eratosthenes 学习初等数论的时候曾经学过埃拉托斯特尼筛法(Sieve of Eratosthenes),这是一种非常古老但是非常有效的求解\(p_n\)的方法,其原理非常简单:从2开始,将每个素数的各个倍数都标记成合数。 其原理如下图所示: 图引自维基百科 埃拉...

weixin_30466953的博客 313

面试官:你知道怎么求素数吗?

摘要:面试官:你知道怎么求素数吗?我:求素数?

华为云官方博客 3934

java语言中如何表示素数,使用Java语言求素数的几个方法

使用Java语言求素数的几个方法今天找了一篇"面试50题"的文档,第一题是求fibonacci数列,使用递归很容易就实现了,没什么难度.第二题是输出101~200之间的素数,没用太长时间也做了出来,代码如下for (int i=101;i<=200;i++) {//计算到i的开方为止int dest=(int)(Math.sqrt(i));for (int j=2;j<=(int)(M...

weixin_36446632的博客 2139

根号法、埃氏法、欧拉筛选。三种方法求素数

先上开根号求素数 一个数N的最小质因子,必定小于开根号N: 数学表达:a*b=N,若a开根号N,所以只要求2~开根号N,即可判断N是不是素数。 反证法 如果数N的最小质因子a大于开根号N,那数N的另一个因子b,(b和a构成一对N的约数), 必定大于a,那么也大于根号N, 这时候,a*b必定大于N,所以原命题正确 自己的证明:一个数N,那么有 0~开跟号N=>左

p13132312312的博客 3411

python求小于n的所有素数_快速找出N以内的所有素数解法,python版本。这个应该是最快的了...

原博文2013-11-21 19:49 −作者:Raffeale/于大伟 质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。 一般正常人的解法是两次循环,假设求小于N的所有素数。一次用N-1之间的所有数去除,如果能被整除这个数肯定不是素数。否则是素数。 这个解题的基本思路: 一个数是否是素数其实不需要去...相关推荐2013-11-21 19:52 −作者:R...

weixin_39622217的博客 1534

素数判断及筛法

单个素数判断 //素数判断(小数据) int prime(int n) { if (n == 0 || n == 1) return 0; if (n == 2) return 1; if (n % 2 == 0) return 0; for (int i = 3; i * i <= n; i = i + 2) if (n

acm2016 428

如何求素数

如何求素数1。自然数是0,1,2……2。素数是2,3,5……(不包括1的只能背1和它本身整除的自然数)public class Test {  /*  * 最普通的算法:  * 打印num以内的素数并返回素数个数  * n、m分别为外、内层循环,i是第几个素数,s是素数个数  */ public int prime(int num){  int n,m,i=0,s=0;   label1:   for(n=2;n  {    for(m=2;m   {     if(n%m==0)     continue

skywalker_sun的专栏 1406

求素数方法

(一)      一般求素数方法(对某些OJ 来说会超时)     /*求素数的三种方法     一:for(i=2;i if(n%i==0)i 在2 到n-1 之间任取一个数,如果n 能被整除则不是素数,否则就是素数     二:for(i=2;i if(n%i==0) /*i 在2 到n/2 之间任取一个数,如果n 能被整除则不是素数,否则就是素数          三:for(

gchichafengyun的专栏 1055
上一篇: C++中关于操作符先(++)后(++)问题的讨论
下一篇: 深入探讨this指针
逸学堂
博客等级 码龄23年 1104粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值