• 关于Eratosthenes筛子算法筛选小于n的素数的理解


    今天在学习Java核心技术第九章集合框架中的BitSet时,遇到了这个算法。Eratosthenes筛子算法时一个查找素数的方法,这并不是查找素数的最好方法,但是测试编译程序性能的一种流行的基准。

    一、BitSet位集

      BitSet类用于存放一个位序列,它将位包装在字节里,比使用Boolean对象的ArrayList更加高效。

      BitSet类的常用方法有

         BitSet(int initialCapacity)  创建一个位集,规定了它的容量。 index从0开始,长度会随需要增加。

         int length()  返回位集的而逻辑长度,即位集的最高设置位的索引 + 1.

         boolean get(int bit)  获得一个位

         void set(int bit)  设置一个位为true

         void clear(int bit)  清除一个位为false

         void and(BitSet set)  两个位集相“与”

         void or(BitSet set)  两个位集“或”

         void xorBitSet set) 两个位集“异或”

         void andNot(BitSet set) 清除这个位集中对应另一个位集中设置的位

    二、Eratosthenes筛子算法

      本算法的思想如下

      1,创建一个从2到n的连续数组

      2,创建一个变量p等于2(第一个素数)

      3,从p2开始,标记所有大于等于p2,让其中一个因子p自增,且乘积小于等于n的程式。例如p(p+1),p(p+2),……

      4,找到大于p的第一个未被标记的数字,让p等于它,重复第三步。

    下面我们用图片来更加具体的解释一下这个过程 (以下部分转自https://www.geeksforgeeks.org/sieve-of-eratosthenes/   如有侵权,请联系我删除)

      

    Let us take an example when n = 50. So we need to print all print numbers smaller than or equal to 50.

    We create a list of all numbers from 2 to 50.
    Sieve1

    According to the algorithm we will mark all the numbers which are divisible by 2 and are greater than or equal to the square of it.
    sieve2

    Now we move to our next unmarked number 3 and mark all the numbers which are multiples of 3 and are greater than or equal to the square of it.
    SieveofEratosthenes3

    We move to our next unmarked number 5 and mark all multiples of 5 and are greater than or equal to the square of it.
    Sieve4

    We continue this process and our final table will look like below:
    Sieve5

    So the prime numbers are the unmarked ones: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47.

    Thanks to Krishan Kumar for providing above explanation.

    三、代码实现

      下面我们给出两种实现:第一种使用BitSet位集来标记筛选出去的数字索引

      

            int n = 50;
            BitSet b = new BitSet(n + 1);
            int count = 0;
            int i;
            for (i = 2; i <= n; i++) {
                b.set(i);
            }
            i = 2;
            while (i * i <= n) {
                if (b.get(i)) {
                    count++;
                    System.out.println(i);
                    int k = 2* i;
                    while (k <= n) {
                        b.clear(k);
                        k += i;
                    }
                }
                i++;
            }
            while (i <= n) {
                if (b.get(i)) {
                    System.out.println(i);
                    count++;
                }
                i++;
            }                

    第二种用布尔数组实现

    void sieveOfEratosthenes(int n) 
        { 
            // Create a boolean array "prime[0..n]" and initialize 
            // all entries it as true. A value in prime[i] will 
            // finally be false if i is Not a prime, else true. 
            boolean prime[] = new boolean[n+1]; 
            for(int i=0;i<n;i++) 
                prime[i] = true; 
              
            for(int p = 2; p*p <=n; p++) 
            { 
                // If prime[p] is not changed, then it is a prime 
                if(prime[p] == true) 
                { 
                    // Update all multiples of p 
                    for(int i = p*p; i <= n; i += p) 
                        prime[i] = false; 
                } 
            } 
              
            // Print all prime numbers 
            for(int i = 2; i <= n; i++) 
            { 
                if(prime[i] == true) 
                    System.out.print(i + " "); 
            } 
        } 
  • 相关阅读:
    每天读一下,你就会改变
    C++ 反转字符串(原创)
    C++ string学习
    18种常见室内花卉的功效 (转自网络)
    UML建模教程
    孙鑫视频VC++深入详解学习笔记
    visual C++ 6.0开发工具与调试
    C++ typeid typename使用
    C++模板学习
    Working classes Code complete reading notes(6)
  • 原文地址:https://www.cnblogs.com/Joey777210/p/11877865.html
Copyright © 2020-2023  润新知