我正在实现一个相当快的质数生成器,并且通过对Eratosthenes进行了一些优化,获得了一些不错的结果。特别是,在算法的初级阶段,我以这种方式跳过了2和3的所有倍数:
template<class Sieve, class SizeT> void PrimeGenerator<Sieve, SizeT>::factorize() { SizeT c = 2; m_sieve[2] = 1; m_sieve[3] = 1; for (SizeT i=5; i<m_size; i += c, c = 6 - c) m_sieve[i] = 1; }
m_sieve根据Eratosthenes的筛子,这是一个布尔数组。我认为这是一种仅考虑素数2和3的Wheel分解,然后按照模式2、4、2、4 ..递增。
m_sieve
我想做的是实现更大的转轮,也许考虑素数2,3和5。
我已经阅读了很多有关它的文档,但是我没有看到用Eratosthenes筛子实现的任何实现……示例代码可能会有所帮助,但也有些提示会很不错:)谢谢。
您可以走得更远。这是几年前我写的一些OCaml代码:
let eratosthene borne = let remove_multiples a lst = let rec remmult multa li accu = function [] -> rev accu | head::tail -> if multa = head then remmult (a*(hd li)) (tl li) accu tail else remmult multa li (head::accu) tail in remmult (a * a) lst [] lst in let rec first_primes accu ll = let a = hd ll in if a * a > borne then (rev accu) @ ll else first_primes (a::accu) (remove_multiples a (tl ll)) in let start_list = (* Hard code of the differences of consecutive numbers that are prime*) (* with 2 3 5 7 starting with 11... *) let rec lrec = 2 :: 4 :: 2 :: 4 :: 6 :: 2 :: 6 :: 4 :: 2 :: 4 :: 6 :: 6 :: 2 :: 6 :: 4 :: 2 :: 6 :: 4 :: 6 :: 8 :: 4 :: 2 :: 4 :: 2 :: 4 :: 8 :: 6 :: 4 :: 6 :: 2 :: 4 :: 6 :: 2 :: 6 :: 6 :: 4 :: 2 :: 4 :: 6 :: 2 :: 6 :: 4 :: 2 :: 4 :: 2 :: 10 :: 2 :: 10 :: lrec and listPrime2357 a llrec accu = if a > borne then rev accu else listPrime2357 (a + (num (hd llrec))) (tl llrec) (a::accu) in listPrime2357 (num 11) lrec [] in first_primes [(num 7);(num 5);(num 3);(num 2)] start_list;;
请注意,OCaml允许循环链接列表的妙招。