素数算法的优化之路

素数算法的优化之路素数算法的优化之路

大家好,又见面了,我是你们的朋友全栈君。一、素数的定义


        质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数(不包括0)整除的数。因为合数是由若干个质数相乘而得来的,所以,没有质数就没有合数,由此可见质数在数论中有着很重要的地位。


        比如:2,3,5,7,9…..都是素数。


 


二、构造素数算法


     写算法之前,先来说说以下这个东西:
     
     对于任意一个合数n,如果它有两个质因子x,y,显然n = x*y, 
     所以,由不等式性质可得,x <= sqrt(n), 即 x <= n^(1/2)。
     
     推广一下,对于任意一个合数,如果它有k个质因子x1,x2,x3,…. ,xk,显然n = x1 * x2 * x3 * …. * xk,
     所以,由不等式性质可得, x <= n^(1/k),即每个质因子必小于或者等于n开k次方,其中x 属于集合{ 

x1,x2,x3,…. ,xk 
}。

    定义一个全局变量和一个全局数组,要是数组是分配在栈上的话,是有容量限制的,所以我们就定义个全局的。

     const unsigned int N = 50000;
     bool flag[N+1];


 

  
  1、算法一:按照定义,即可快速写出一个简单的构造素数算法
 


    

void PrimeCreateCommon()//按照定义
{
	for ( unsigned int i = 2; i <= N; ++i )
	{
		//由前面的铺垫,这里不难理解吧。因为我不知道这个数有几个质因子,
		//我就假设它只有两个,范围拉大一些,这个数的所有质因子都小于或
		//等于sqrt( (double)i ) + 1。其它的约数,必然是这些质因子的倍数
		//而已所以就没必要继续除下去了。
		bool flag = true;
		for ( unsigned int j = 2; j <= sqrt((double)i)+1; ++j )  
		{                              
			if ( i % j == 0 )         
			{                        
				flag = false;
			}
		}
		//if ( flag )
		//{
		// 	cout << i << " "; 
		//}
	}
	cout << endl;
}




   分析:该算法的时间复杂度为O(n*sqrt(n) ),在n比较大时(比如n = 50000),我的机器跑了个二十来秒,就也叫算法,呵呵,所以接下来我们来看另一种算法 ,那就是
古希腊数学家的埃拉托色尼给出的一个比较省力的算法——埃拉托色尼筛法
 




   2、算法二:筛选法

 


    首先,列出从2开始的数。然后,将2记在素数列表上,再划去所有2的倍数。根据定义,剩下的最小的数——在这里是3——必定是素数。将这个数记在素数列表上,再划去所有它的倍数,这样又会剩下一些数,取其中最小的,如此反复操作。最后剩下的都是素数。
   

void PrimeCreateExt()//筛选法优化
{
	memset( flag, 0, (N+1)*sizeof(bool) );
	for ( unsigned int i = 2; i <= sqrt(double(N)) + 1; ++i )
	{
		if ( !flag[i] )
		{
			for ( unsigned int j = 2*i; j <= N; j += i )
			{
				flag[j] = true;
			}
		}

	}

// 	for ( int i = 2; i <= N; ++i )
// 	{
// 		if ( !flag[i] )
// 		{
// 			cout << i << " ";
// 		}
// 	}
// 	cout << endl;
} 


 三、两种算法的运行时间对比
    
  

//测试函数
int main()
{
	clock_t start, finish;
	double duration = 0.0;

	cout << "筛选算法产生素数:" << endl;
	start = clock();
	PrimeCreateExt();
	finish = clock();
	duration = (double)(finish-start);
	cout << "时间消耗:" << duration << "ms" << endl << endl;

	cout << "普通算法产生素数:" << endl; 
	start = clock();
	PrimeCreateCommon();
	finish = clock();
	duration = (double)(finish-start);
	cout << "时间消耗:" << duration << "ms" << endl << endl; 
} 

   

 //产生50万以内的素数运行时间对比 

素数算法的优化之路

 四、空间上的优化
            略


作者:山丘儿
转载请标明出处,谢谢。原文地址:http://blog.csdn.net/s634772208/article/details/46327281

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/151674.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 史上最详细的虚拟机VMware12安装Windows7教程「建议收藏」

    摘要:VMware是一个强大的虚拟机,可以在一台电脑上模拟真实的环境,创建出一个虚拟机系统,并且可以在这个系统进行测试和其他的操作,当然你也可以直接网上下载现成的虚拟机镜像或者,网络上有很多的Ghost等文件,这类系统可能经过别人一些优化,但是优化的过程可能阉割了某些系统的文件,或者被植入一些广告等,文本一步步详细说明如何利用VMware12安装一个Win7系统,虚拟机win7镜像文件iso…

    2022年4月12日
    42
  • docker(11)Dockerfile 中的COPY与ADD 命令[通俗易懂]

    docker(11)Dockerfile 中的COPY与ADD 命令[通俗易懂]前言Dockerfile中提供了两个非常相似的命令COPY和ADD,本文尝试解释这两个命令的基本功能,以及其异同点,然后总结其各自适合的应用场景。Build上下文的概念在使用dock

    2022年7月31日
    7
  • 基于最简单的FFmpeg采样读取内存读写:存储转

    基于最简单的FFmpeg采样读取内存读写:存储转

    2022年1月1日
    53
  • matlab中wavedec2,wavedec2函数详解[通俗易懂]

    matlab中wavedec2,wavedec2函数详解[通俗易懂]很多人对小波多级分解的wavedec2总是迷惑,今天就详释她!wavedec2函数:1.功能:实现图像(即二维信号)的多层分解,多层,即多尺度.2.格式:[c,s]=wavedec2(X,N,’wname’)[c,s]=wavedec2(X,N,Lo_D,Hi_D)(我不讨论它)3.参数说明:对图像X用wname小波基函数实现N层分解,这里的小波基函数应该根据实际情况选择,具体选择办法可以搜之或者…

    2022年7月24日
    12
  • BeanUtils工具类常用方法「建议收藏」

    BeanUtils工具类常用方法「建议收藏」        BeanUtils是Apachecommons组件的成员之一,主要用于简化JavaBean封装数据的操作。它可以给JavaBean封装一个字符串数据,也可以将一个表单提交的所有数据封装到JavaBean中。使用第三方工具,需要导入jar包:BeanUtils工具常用工具类有两个:BeanUtils、ConvertUtils。BeanUtils用于封装数据,ConvertUti…

    2022年9月11日
    3
  • java多线程编程实例

    java多线程编程实例        这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下。1.相关知识:Java多线程程序设计到的知识:(1)对同一个数量进行操作(2)对同一个对象进行操作(3)回调方法使用(4)线程同步,死锁问题(5)线程通信等等2.示例2.1三个售票窗口同时出售20张票程序分析:    (1)票数要使用同一…

    2022年6月2日
    63

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号