求[1,n]之间的所有素数

package primenumber.s1;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/10 21:53
 * 求出[1,n]之间的所有素数
 * 最原始的做法
 */
public class TestPrimeNumber {
    //统计遍历的次数
    private static int opsNum = 0;

    public static void main(String[] args) {
        //假设求1-100以内的所有素数
        int n = 100;
        for(int i=2; i < n; i++) {
            boolean isPrime = isPrime(i);
            //如果是素数,则打印出来
            if(isPrime) {
                System.out.println(i);
            }
        }
        System.out.println("Total loop times:" + opsNum);
    }

    /**
     * 判断是否为素数
     * @param n    待判断的数字
     * @return
     */
    private static boolean isPrime(int n) {
        //若传入的数字n小于2,则直接return false,因为最小的素数为2
        if(n < 2) {
            return false;
        }
        //从2遍历到n-1
        for(int i = 2; i < n; ++i) {
            opsNum++;
            //如果发现能被其中任意一个数整除,那么说明数字n不是素数
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
}
package primenumber.s2;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/10 21:53
 * 求出[1,n]之间的所有素数
 */
public class TestPrimeNumber {
    //统计遍历的次数
    private static int opsNum = 0;
    public static void main(String[] args) {
        //假设求1-100以内的所有素数
        int n = 100;
        for(int i=2; i < n; i++) {
            boolean isPrime = isPrime(i);
            //如果是素数,则打印出来
            if(isPrime) {
                System.out.println(i);
            }
        }
        System.out.println("Total loop times:" + opsNum);
    }

    /**
     * 判断是否为素数
     * @param n    待判断的数字
     * @return
     */
    private static boolean isPrime(int n) {
        //若传入的数字n小于2,则直接return false,因为最小的素数为2
        if(n < 2) {
            return false;
        }
        if(n == 2) {
            return true;
        }
        //如果传入的数字是偶数,那么一定不是素数
        if(n%2==0) {
            return false;
        }
        //从3开始遍历剩下的所有奇数
        for(int i = 3; i < n; i += 2) {
            opsNum++;
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
}
package primenumber.s3;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/10 21:53
 * 求出[1,n]之间的所有素数
 * 定理: 如果n不是素数, 则n有满足1< d<=sqrt(n)的一个因子d.
 * 证明: 如果n不是素数, 则由定义n有一个因子d满足1< d< n.
 * 如果d > sqrt(n), 则 1/d <= √n ==> n/d <= √n
 * 则n/d是满足1 < n/d <= sqrt(n)的一个因子.
 */
public class TestPrimeNumber {
    //统计遍历的次数
    private static int opsNum = 0;
    public static void main(String[] args) {
        //假设求1-100以内的所有素数
        int n = 100;
        for(int i=2; i < n; i++) {
            boolean isPrime = isPrime(i);
            //如果是素数,则打印出来
            if(isPrime) {
                System.out.println(i);
            }
        }
        System.out.println("Total loop times:" + opsNum);
    }

    /**
     * 判断是否为素数
     * @param n    待判断的数字
     * @return
     */
    private static boolean isPrime(int n) {
        //若传入的数字n小于2,则直接return false,因为最小的素数为2
        if(n < 2) {
            return false;
        }
        if(n == 2) {
            return true;
        }
        //如果传入的数字是偶数,那么一定不是素数
        if(n%2==0) {
            return false;
        }
        //遍历从3到根号n之间的所有奇数
        for(int i = 3; i*i <= n; i += 2) {
            opsNum++;
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
}
package primenumber.s4;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/10 21:53
 * 求出[1,n]之间的所有素数
 * 定理: 若A = B * C且B <= C,B是能整除A的最小数字,那么B一定是素数
 * 证明: 假设B不是素数,那么对于B一定存在这样的等式B=P*M,此时P肯定小于B,
 *      B能整除A,那么P也一定能够整除A,那么说明B一定不是能整除A的最小数字,
 *      然而此时推理与题设提交相矛盾,由此证明"B不是素数"这个假设不成立即B一定是素数,
 *      从而定理得以证明.
 *      另外,根据题设中的条件: A = B * C且B <= C,我们可以得出:
 *      B * B <= A ==> B <= √A
 */
public class TestPrimeNumber {

    public static void main(String[] args) {
        //假设求1-100以内的所有素数
        int n = 100;
        boolean[] result = getPrimes(n);
        for(int i=2; i < n; i++) {
            boolean isPrime = result[i - 1];
            //如果是素数,则打印出来
            if(!isPrime) {
                System.out.println(i);
            }
        }
    }

    /**
     * 判断是否为素数
     * @param n    待判断的数字
     * @return
     */
    private static boolean isPrime(int n) {
        boolean[] result = getPrimes(n);
        return !result[n-1];
    }

    /**
     * 标记[1,n]之间的所有素数
     * @param n
     * @return
     */
    private static boolean[] getPrimes(int n) {
        //统计遍历的次数
        int opsNum = 0;
        //使用一个数组标记[1,n]之间的每个数字是否为素数,false表示素数,true表示合数
        boolean[] isPrimes = new boolean[n];
        //这里的变量i即上面定理中的B,之所以是i * i < n,是由我们推断出的结论:B <= √A演化而来
        for(int i=2; i * i <= n; i++) {
            //若为合数,则直接跳过
            if(isPrimes[i - 1]) {
                continue;
            }
            // i * j <= n即B * C不能大于A,由A = B * C可知
            for(int j = 2; i * j <= n; j++) {
                //此时i * j一定是合数
                isPrimes[i * j - 1] = true;
                //统计遍历次数,主要是为了了解算法的性能
                opsNum++;
            }
        }
        System.out.println("Total loop times:" + opsNum);
        return isPrimes;
    }
}
package primenumber.s5;

/**
 * Created by Lanxiaowei
 * Craated on 2016/12/10 21:53
 * 求出[1,n]之间的所有素数[最高效的算法,算法复杂度O(n)]
 * 定理: 拿已知的素数列表去过滤合数,那么能够保证被过滤掉的合数有且只被过滤一次
 */
public class TestPrimeNumber {

    public static void main(String[] args) {
        //假设求1-100以内的所有素数
        int n = 100;
        boolean[] result = getPrimes(n);
        for(int i=2; i < n; i++) {
            boolean isPrime = result[i - 1];
            //如果是素数,则打印出来
            if(!isPrime) {
                System.out.println(i);
            }
        }
    }

    /**
     * 判断是否为素数
     * @param n    待判断的数字
     * @return
     */
    private static boolean isPrime(int n) {
        boolean[] result = getPrimes(n);
        return !result[n-1];
    }

    /**
     * 标记[1,n]之间的所有素数
     * @param n
     * @return
     */
    private static boolean[] getPrimes(int n) {
        //统计遍历的次数
        int opsNum = 0;
        //使用一个数组标记[1,n]之间的每个数字是否为素数,false表示素数,true表示合数
        boolean[] isPrimes = new boolean[n];
        //目前已知的素数
        int[] primeList = new int[n];
        //目前已知素数列表索引
        int p = 0;
        for(int i=2; 2 * i <= n; i++) {
            //若为素数,则记录到目前已知的素数数组中
            if(!isPrimes[i - 1]) {
                primeList[p++] = i;
            }
            //遍历目前已知的素数来过滤合数
            for(int j = 0; j < p; j++) {
                if(i * primeList[j] <= n) {
                    // i * primeList[j]一定是合数,因为已知primeList[j]是素数,而i > 1,因此得以证明i * primeList[j]一定是合数.
                    isPrimes[i * primeList[j] - 1] = true;
                    //统计遍历次数,主要是为了了解算法的性能
                    opsNum++;
                }

                // 如果i不是一个素数
                if(i % primeList[j] == 0) {
                    break;
                }
            }
        }
        System.out.println("Total loop times:" + opsNum);
        return isPrimes;
    }
}

猜你喜欢

转载自iamyida.iteye.com/blog/2344222