求素数列表和判断素数的算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

求素数列表和判断素数的算法

有兴趣阅读本文的读者,应该对素数概念是十分熟悉的了。用计算机程序实现素数计算,集中在2个主要问题上:

∙判断一个正整数是否是素数-(算法A)

∙求一定范围内的素数列表- (算法B)

关于素数的算法,根据素数的数学性质,大家都会想到如下几个方面:

∙用遍历求模的方式判断素数

∙素数都是奇数,可以在奇数数列中寻找素数

∙利用开方来缩小搜索的范围

然后,求素数的计算是复杂的,如果算法写得不好,则耗时较高。在百度百科“素数”条目中的算法程序,是值得商榷的。很多方法是O(N2)的算法。

为此,在本文中探讨了求素数列表和判断素数这两个算法,力图使算法可以达到O

(N Log(N))优化级别。在本文中,算法语言选用C#。

1,判断素数的简单实现(算法A-1)

///

///算法A-1,判断素数

///

///待测正整数

///是否为素数(为了简化,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 Primes { get; set; }

///

///算法A-2,判断素数

///

///待测正整数

///是否为素数(为了简化,1以下的整数皆为素数)

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 primeList = new 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 primeList = new List();

int index = 1; // 步长下标

int[] loops = new int[] { 2, 4 };//步长

相关文档
最新文档