素数定义是除了1以外,最小因子是自己的数。
针对这个定义,一个简单的判断n是否是素数算法:从2开始直到n-1的数如果都不能被n整除,那么n是素数。
此算法进一步简化为:从2开始直到小于等于n的平方根的数如果都不能被n整除,那么n是素数。
此判断依据是:假设a是n的因子,b=n/a,那么a*b=n,可以推论a和b不能都大于n的平方根。
所以一个数如果是素数,在小于等于这个数的平方根范围内必然没有因子。
以下代码枚举了2到数字n范围的素数:
;enum, is prime number
(define (prime-num1? x)
(define (iter t)
(or (> (expt t 2) x) (and (not (= (remainder x t) 0)) (iter (+ t 1)))))
(iter 2))
(define (enum-prime-num1 n)
;enum prime number
(define (enum x c)
(if (<= x n) (enum (+ x 1) (if (prime-num1? x) (cons x c) c)) c))
(enum 2 (list )))
显然,这个算法的步数具有数字n的平方根的增长阶。
另一个判断素数的方法,费马定理,用scheme语法描述为:
如果 (and (prime-num? n) (> a 0) (< a n) ;如果n是素数,a>0并且a<n
那么 (= (remainder (expt a n) n) a) ;那么a的n次方对n取模等于a对n取模,因为a小于n,所以可以简化为
a的n次方对n取模等于a
;femat, is prime-num (define (prime-num2? x) (define (iter t) (or (= t 0) (and ((lambda (a) (= (remainder (expt a x) x) a)) (+ 1 (random (- x 1)))) (iter (- t 1))))) (iter (if (< x 10) x 10))) (define (enum-prime-num2 n) ;enum prime number (define (enum x c) (if (<= x n) (enum (+ x 1) (if (prime-num2? x) (cons x c) c)) c)) (enum 2 (list )))
运行这两个示例如下:
发现问题了!同样是求1000以内的素数,2个算法的结果不一样,区别就在数字561,这个数不是素数,但是费马定理把这个数判定为素数。这个561被称为伪质数,确实存在一些数能骗过费马定理的检查。