算法-----求n以内素数(质数)

求n以内素数(质数)。


java版

这道题看到一眼就能想到一个for循环,对每个数取余,如果==0,说明能除断,就不是素数(质数)。

1、如果用上面的方法去做,当n小的时候,没什么,当n数据大的时候,效率就是一个问题,做了很多无用判断。

改进:

1、所有的偶数都不是素数(质数),所以不用对偶数进行判断取余。

2、第一个可能想到,大于该数1/2的数都不能整除,(例如:该数100除以50(不包括50)之后的数都不可能整除)

    但是,经规律实验证明 ,大于该数的二次根的数都不能整除。

CODE:

package com.company;

/**
 * 求100以内素数(质数) 最终方案:不需要循环每一次判断,
 * 1.所有偶数都不是质数
 * 2.所有奇数除以偶数都除不断,只需要判断对奇数取余,减少判断次数
 * 3.大于该数字二次根的数字 是不能整除的。减少循环数字范围。
 */
public class PrimeNumber {

    private boolean isPrimeNumberFour(int number) {
        double sqrt = Math.sqrt(number); //必须把 Math.sqrt(number) 提前赋值好,要不然放在 sqrt 处,每次比较都会计算一次,影响性能。
        for (int j = 3; j < sqrt; j+=2) {
            if (number % j == 0) return false;
        }
        return true;
    }
    private void methodFour(int number) {
        long start = System.currentTimeMillis();
        if (number>=2) System.out.println("Number:2 Is Prime Number");
        for (int i = 3; i < number; i+=2) {
            if (isPrimeNumberFour(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodFour 花费时间:"+(end-start)+"ms");
    }
    public static void main(String[] args) {
        PrimeNumber primeNumber = new PrimeNumber();
        primeNumber.methodFour(100000);
    }

}

上面的是效率最高的一种方式。

 

以下的CODE,是我对4种方式的效率比较:

package com.company;

/**
 * 求100以内素数(质数) 最终方案:不需要循环每一次判断,
 * 1.所有偶数都不是质数
 * 2.所有奇数除以偶数都除不断,只需要判断对奇数取余,减少判断次数
 * 3.大于该数字二次根的数字 是不能整除的。减少循环数字范围。
 */
public class PrimeNumber {
    //第一种方法
    private boolean isPrimeNumberOne(int number) {
        for (int j = 2; j < number; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodOne(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberOne(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodOne 花费时间:"+(end-start)+"ms");
    }

    //第二种方法
    private boolean isPrimeNumberTwo(int number) {
        for (int j = 2; j < number/2; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodTwo(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberTwo(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodTwo 花费时间:"+(end-start)+"ms");
    }

    //第三种方法
    private boolean isPrimeNumberThree(int number) {
        double sqrt = Math.sqrt(number); //必须把 Math.sqrt(number) 提前赋值好,要不然放在 sqrt 处,每次比较都会计算一次,影响性能。
        for (int j = 2; j < sqrt; j++) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodThree(int number) {
        long start = System.currentTimeMillis();
        for (int i = 2; i < number; i++) {
            if (isPrimeNumberThree(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodThree 花费时间:"+(end-start)+"ms");
    }

    //第四种方法
    private boolean isPrimeNumberFour(int number) {
        double sqrt = Math.sqrt(number); //必须把 Math.sqrt(number) 提前赋值好,要不然放在 sqrt 处,每次比较都会计算一次,影响性能。
        for (int j = 3; j < sqrt; j+=2) {
            if (number % j == 0) return false;
        }
        return true;
    }

    private void methodFour(int number) {
        long start = System.currentTimeMillis();
        if (number>=2) System.out.println("Number:2 Is Prime Number");
        for (int i = 3; i < number; i+=2) {
            if (isPrimeNumberFour(i)) System.out.println("Number:"+i+" Is Prime Number");
        }
        long end = System.currentTimeMillis();
        System.out.println("methodFour 花费时间:"+(end-start)+"ms");
    }


    public static void main(String[] args) {
        PrimeNumber primeNumber = new PrimeNumber();
        long start = System.currentTimeMillis();
        primeNumber.methodOne(500000);
        long end = System.currentTimeMillis();
        long methodOne = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodTwo(500000);
        end = System.currentTimeMillis();
        long methodTwo = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodThree(500000);
        end = System.currentTimeMillis();
        long methodThree = end - start;
        start = System.currentTimeMillis();
        primeNumber.methodFour(500000);
        end = System.currentTimeMillis();
        long methodFour = end - start;
        System.out.println("one:"+methodOne+"two:"+methodTwo+"three:"+methodThree+"four:"+methodFour);
    }

}

四种方式,以50W的数据测试:(单位是ms)

one:30321two:13883three:343four:289

我们可以看到,30s,13s,0.34s,0.28s。这个差距还是挺大的。

当数据量更大的时候,这些差距会更加明显

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值