簡體   English   中英

有人能解釋一下下面的素數生成方法嗎?

[英]Can someone explain me the following prime number generation method?

我想下面的方法使用Sieve of Eratosthenes (包含 - 排除算法)來生成最多給定數量的素數。 我特別不明白的是,為什么它清除(j/2)位置上設置的位。 是否遵循了特定的規則? BitSet包含在位置x處設置的位,該數字是素數或是復合數。 所以,我無法跟蹤發生的事情。

public static List<Integer> generatePrimes(int max) {
        BitSet primeSet = new BitSet(max / 2);
        primeSet.set(1, max / 2);
        int limit = (int) Math.sqrt(max);
        for (int i = 3; i <= limit; i += 2) {
            if (!primeSet.get(i / 2)) continue;
            for (int j = i * i; j < max; j += i * 2)
                primeSet.clear(j / 2);

        }

        List<Integer> listOfPrimes = new ArrayList<>();
        listOfPrimes.add(2);
        for (int i = primeSet.nextSetBit(0); i >= 0; i = primeSet.nextSetBit(i + 1)) {
            listOfPrimes.add(i * 2 + 1);
        }
        return listOfPrimes;
    }

似乎算法試圖通過使primeSet 表示奇數來節省內存。 因此,重復乘法和除以2。

涉及primeSet.clear()的循環只是將i每個倍數標記為復合。

public static List<Integer> generatePrimes(int max) {

 BitSet primeSet = new BitSet(max / 2);  // host the numbers i up to max/2
 primeSet.set(1, max / 2);               // representing the odds (2i+1)
 int limit = (int) Math.sqrt(max);       //                      below max
 for (int i = 3; i <= limit; i += 2)        // enumerate odds in range 
 {                                          //       3 .. sqrt(max)
     if (!primeSet.get(i / 2)) continue;    // i=2k+1, i/2==(2k+1)/2== k
                                            // (here i is value, k is index)
     for (int j = i * i; j < max; j += i * 2)  // j=i*i is the first multiple
         primeSet.clear(j / 2);        // of i, where the marking off begins
 }                                     //  with step 2*i: 3: 9,6,15,21,...
                                       //                 7: 49,63,77,91,...
 List<Integer> listOfPrimes = new ArrayList<>();
 listOfPrimes.add(2);                     // 2 is known to be prime a priori
 for (int i = primeSet.nextSetBit(0);     // starting with first set bit in
                                          //                 BitSet primeSet,
          i >= 0;                         // 1: until the end of primeSet  
          i = primeSet.nextSetBit(i + 1)  // 3: and go to next set bit
          ) {
     listOfPrimes.add(i * 2 + 1);         // 2: add 2i+1 to the list of primes,
 }                                        // (here i is index)
 return listOfPrimes;
}

th number, starting from n 2 , as apparently one Rev. Samuel Horsley FRS knew back in 1772 . 作為篩子的一部分,我們必須標記從9開始的每個第三個數字,並且通常每個第個數字,從n 2開始,顯然是一個牧師Samuel Horsley FRS在1772年知道

沿着列表計算是低效的 - 篩選效率的關鍵是通過地址直接訪問內存。 這里數字數字中的數字地址只是數字的值本身( 值和地址的這種混合也是各種整數排序方法效率的關鍵)。

要直接計算每個第3個奇數,我們必須將6添加到前一個以獲得下一個。 對於每個第5個,我們添加10個,每個i th - 2*i


順便提一下,這個代碼可以略微改進。 對於它們之間的距離2*i處的數字,集合中的索引將位於距離i 無需一直刪除2,只需計算起始索引和i增量即可。


編輯:該代碼等效於以下偽代碼:

defn primes(max):
  sieve := makeArray(3,5,7 ... max, True)
  for p from 3 to sqrt(max) step 2:
    if sieve[p]:
        for i from p * p to max step 2*p:
            sieve[i] := False
  primes = {2} + {all i in (3,5,7, ... max) such that sieve[i] is True}

除2之外的所有偶數都不是素數,因此不需要迭代它們。

primeset的位表示數字2x + 1,其中x是位集的索引。 因此,當你的primeset包含{1,2,3,5,6,8,9,11,14}時,它們代表數字{3,5,7,11,13,17,19,23,29}。

如果你對素數編程感興趣,我謙虛地在我的博客上推薦這篇文章 除此之外,它解釋了Eratosthenes的Sieve以及導致你悲傷的計算。

編輯:添加簡單的Eratosthenes篩選,如評論中所述。

function primes(n)
    sieve := makeArray(2..n, True)
    for p from 2 to n step 1
        if sieve[p]
            output p
            for i from p * p to n step p
                sieve[i] := False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM