求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。这个差距还是挺大的。
当数据量更大的时候,这些差距会更加明显