例3、求出2~n之间的素数。
由希腊数学家Eratosthense提出“筛法”,步骤如下:(以2到20为例)
①将所有的候选数放入筛子集合中;[1,2,3,4,…,20], 素数集合为 []。
②找筛中最小数(必为素数)next,放入素数集合中;
③将next的所有倍数从筛中筛去;
④重复②~③,直到筛空。素数集合中即所求。每次循环如下:
筛子集合 素数集合
[3,5,7,9,11,13,15,17,19] [2]
[5,7,11,13,17,19] [2,3]
[7,11,13,17,19] [2,3,5]
…… ……
[] [2,3,5,7,11,13,17,19]
定义变量作用:N:限定素数范围
sieve 存放全部数字
primes 存放素数
while j<=n do
begin sieve:= sieve-[j]; j:=j+next end { 将next的倍数从筛中筛去 }
until sieve=[];
for next:=2 to n do
if next in primes then write(next:5); { 输出素数集合中的所有元素}
writeln
end.
//next=2 2加入素数 去掉2的倍的所有数
const n=200;
var sieve,primes:set of 2..n;
j,next:integer;
begin
sieve:=[2..n]; primes:=[]; { 将所有的候选数放入筛中,素数集合置空 }
next:=2;
repeat
while not(next in sieve) do //KBK
next:=succ(next); { 找筛中最小数next ,筛去的数的下一个数}
primes:= primes+[next]; { 将筛中最小数next,放入素数集合中 }
j:=next;
第一次REAEAT 2在集合中 //KBK不执行,直接调用下面代码去2倍数
第二次REPEAT//KBK被执行(2已被去符合调用,调用前NEXT=2,调用后=3)//去掉3的倍数
第三次REPEAT//KBK被执行 (3已被去符合调用,调用前NEXT=3,调用后=4,因为4是2倍数被去,所以需要再调用一次KBK,调用前NEXT=4,调用后NEXT=5,因为5在集合中,所以执行下面代码去5的倍数);
一次去不是一个不是素数的数,及其倍数,接着又取最小数(上一轮被去的数的下一个,因为是顺序的,在集合中就去它的倍数,不在说明是前面数的倍数被过掉了,在就去其倍数,),一轮一轮的过,最小数必为素数:这是古代人数学家的得出真理。
每过一轮,剩下集合中的最小数必为素数。所为筛子。就是要明白这句话。
[2.3.4.5.6] 2是素数 过一轮[3,5]最小数3必为素数
换种想法:
KBK在整体中的作用就是:顺序的取得素数的下一个数(A)(取得的这个数(A)可能是前面面的倍数去掉的数(用not(next in sieve) 来判断,不在集合中就取下一个,这种方法就取得了2-N素数真理),那么就再取这个去掉的数(A)的下一个(B),(就是找集合中剩下的最小数,顺序比较),)(succ)
利用了序列顺序:倒转:去掉满足的条件(激发因子2),返加到前面:从剩下的条件再利用上次去掉的条件(作为利用因子)来去掉剩下条件满足的条件。利用因子逐惭排除,得到最终想要的结果。
废掉的东东再根据关系法再利用