[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
getting prime numbers quickly
- To: bep@argv.org
- Subject: getting prime numbers quickly
- From: TAKAHASHI Naoto <ntakahas@m17n.org>
- Date: Wed, 11 Jul 2001 16:08:17 +0900 (JST)
- Delivered-To: mailing list bep@argv.org
- Mailing-List: contact bep-help@argv.org; run by ezmlm
- User-Agent: SEMI/1.14.3 (Ushinoya) FLIM/1.14.2 (Yagi-Nishiguchi) APEL/10.2 Emacs/21.0.104 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)
n高橋です。もう誰も読んでないかもしれませんが(苦笑)、更に高速化します。
TAKAHASHI Naoto writes:
> ;; n高橋爆速バージョン
> ;; 6n±1法 (2と3は特別扱い)
> ;; xが素数かどうかは、(sqrt x) までの素数で割って調べる
> ;; 関数呼び出しは重いので、+1と-1の両方の場合をインライン展開
> (let* ((primes '(2 3))
> (tail (last primes))
ここで primes の初期値を '(2 3) としていますが、6n±1法なので2と3で割っ
てみるのは全くの無駄ですね。また最後に primes を値として返すわけでもな
いので、変数名は divisors にでも変えて、初期値は '(5) とした方がいいで
しょう。また '(5) は長さ1のリストなので、次の tail の初期値は
(last divisors) ではなくて単に divisors になります。
また高速化を図るのなら当然バイトコンパイルしますから、わざわざ読みにく
いインライン展開を使わず、defsubst を使うことにします。変数名も、より
整数っぽいものに変えます。結局次のようになります。
;; n高橋爆速バージョン[改]
;; 6n±1法 (2と3は特別扱い)
;; xが素数かどうかは、5以上ルートx以下の素数で割って調べる
;; バイトコンパイルを前提
(defsubst primep (i)
"Internal use only. Depends on external variables."
(setq d divisors
limit (sqrt i))
(while (and (<= (car d) limit) (/= 0 (% i (car d))))
(setq d (cdr d)))
(when (> (car d) limit)
(setcdr tail (list i))
(setq tail (cdr tail))
(insert (format "%s\n" i))))
(let* ((divisors '(5))
(tail divisors)
(n 6)
d limit)
(insert "2\n3\n")
(while (< n 1000)
(primep (1- n))
(primep (1+ n))
(setq n (+ n 6))))
--
TAKAHASHI Naoto
ntakahas@...
http://www.m17n.org/ntakahas/