对于一个数n,判断它是否为素数(质数)。这是一个喜闻乐见的问题。
注意:2是素数,不过下面的算法一般假设所判定数n>2。
最直接方法:
由素数的基本概念出发。
依次判断2~n-1的所有整数能否整除n。如果没有一个能整除的,n就是素数;否则不是素数。
改进方法:
由非素数的因数(1除外)的特点可知,对于非素数n=A*B,非素数的因数中必定有一个小于等于sqrt(n),而与之对应的另一个因数大于等于sqrt(n)。
依次判断2~sqrt(n)的所有整数能否整除n。如果没有一个能整除的,那么sqrt(n)+1~n中的整数也必定不能被整除n,n是素数;否则不是素数。
构造素数表方法:
构造2~n的素数表,存储每个数是否为素数。
除了2之外所有的素数都是奇数,除了2之外所有的偶数一定不是素数。所以,我们构造的素数表只存储奇数是否为素数,3,5,7,9,11......如果是判定数是偶数且不是2,那么直接判断其不是素数,不会构建和查询素数表。素数表的index表示某个数,对应的value表示是否为素数。
素数表的构建方法是,表内所有数初始都设置为素数。从3开始,3是第一个素数,那么令3的不大于n的所有倍数(1倍、2倍、3倍。。。)都设定为非素数。然后,看表中的下一个素数,把其不大于n的所有倍数都设定为非素数。然后再看表中的下一个素数。。。。一直判定到n-1,此时表中状态仍然为素数的数必定是素数。
考虑到要尽可能的节省空间,由于每个数只存储是否的bool状态,我们使用bitmap来存储素数表。对于一个数n,素数表中需要存储(n-1)/2个数的状态,需要(n-1)/16个字节的存储空间。
当需要得到某个大数之前的所有素数的时候,构造素数表的方法是最快的。下面是python语言实现的求小于2000000的所有素数之和。
n = 2000000
a = []
# 0 for prime
# 1 for not prime
for i in xrange(0, n+1):
a.append(0)
a[1] = 1
a[2] = 0
for i in xrange(3, n):
if i%2 == 0:
a[i] = 1
continue
for i in xrange(1, n):
if a[i] == 0:
j = 2
while(i*j < n):
a[j*i] = 1
j += 1
sum = 0
f1 = file('ff.txt','w')
for i in xrange(1, n):
if a[i] == 0:
sum += i
f1.write(str(i)+'\n')
print sum
f1.close()