求素数列表和判断素数的算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
求素数列表和判断素数的算法
有兴趣阅读本文的读者,应该对素数概念是十分熟悉的了。用计算机程序实现素数计算,集中在2个主要问题上:
∙判断一个正整数是否是素数-(算法A)
∙求一定范围内的素数列表- (算法B)
关于素数的算法,根据素数的数学性质,大家都会想到如下几个方面:
∙用遍历求模的方式判断素数
∙素数都是奇数,可以在奇数数列中寻找素数
∙利用开方来缩小搜索的范围
然后,求素数的计算是复杂的,如果算法写得不好,则耗时较高。在百度百科“素数”条目中的算法程序,是值得商榷的。很多方法是O(N2)的算法。
为此,在本文中探讨了求素数列表和判断素数这两个算法,力图使算法可以达到O
(N Log(N))优化级别。在本文中,算法语言选用C#。
1,判断素数的简单实现(算法A-1)
///
///算法A-1,判断素数
///
///待测正整数
///
public static bool IsPrime(int number)
{
// 为了简化,1以下的整数皆为素数
if(number <= 2)
{
return true;
}
// 奇偶性
if (number % 2 == 0)
{
return false;
}
// 利用开方缩小范围,优化效果十分明显
int range = (int)Math.Sqrt(number) + 1;
// 从3开始的奇数列
for (int current = 3; current <= range; current += 2)
{
// 判断是否为素数
if (number % current == 0)
{
// 合数
return false;
}
}
return true;
}
A-1算法中,首先判断奇偶性,再判断从3开始判断待查数(number)是否是合数,若到Math.Sqrt(number)还没有查到是合数,即为素数。
这个方法是O(N1/2)级别的算法,所以很快,即使是最悲观的int.MaxValue,在本人的本机计算也可达到125ms的运行时间。
2,判断素数的优化算法(A-2)
虽然这种算法速度比较快,但如果频繁使用A-1算法,累计起来开销就比较大了,假设有N次访问的话,算法级别就到了O(N3/2)。
因此,本人的解决方案是先计算出一定范围内的素数列表存放在哈希表中,多次调用就可以忽略查询时间了。
///
///素数的Hash表
///
private static HashSet
///
///算法A-2,判断素数
///
///待测正整数
///
public static bool IsPrime2(int number)
{
// 为了简化,1以下的整数皆为素数
if (number <= 2)
{
return true;
}
return Primes.Contains(number);
}
这种算法的前提是要求一个素数表,这就是算法B要研究的问题了。
3 求素数列表的简单算法(B-1)
///
///求素数列表的简单算法(算法B-1)
///
///
///
public static int[] GetPrimes(int range)
{
List
// 从3开始的奇数列
for(int current = 3; current <= range; current += 2)
{
// 判断是否为素数
bool isPrime = true;
foreach (int prime in primeList)
{
if (current % prime == 0)
{
// 若为合数,进入下一数的判断
isPrime = false;
break;
}
}
if (isPrime)
{
// 加入素数列表
primeList.Add(current);
}
}
// 把2补入
primeList.Insert(0, 2);
return primeList.ToArray();
}
上述算法,是对小于N的数,遍历素数表,判断是否为合数,全不成立的即为素数,并加入素数表。
这个算法的一个特点是只对奇数数列进行遍历,从而使遍历次数减少了一半。
4,步长优化的算法(算法B-2)
有读者会想到阴阳素数数列的问题,也就是除了2,3以外,素数要么在(6N-1)数列,要么在(6N+1)数列,这样,是不是就可以通过改变步长方式就可以提高速度?是的,本人也做过这样的实验,代码如下:
///
///求素数列表的简单算法(算法B-2)
///
///
///
public static int[] GetPrimes2(int range)
{
List
int index = 1; // 步长下标
int[] loops = new int[] { 2, 4 };//步长