看起来很简单的一个程序,写起来咋就这么费时间呢?或许这就是所谓的知易行难吧。
当上限增加到10万时(即,输出10万以内的所有素数时,方法1用时约为方法2的四分之一)。选择一个优化的算法有时很重要!
源码:
package exercises.ch6Methods;
//JHTP Exercise 6.25 (Prime Numbers)
//by [email protected]
/*6.25 (Prime Numbers) A positive integer is prime if it’s divisible by only 1 and itself.
* For example, 2, 3, 5 and 7 are prime, but 4, 6, 8 and 9 are not.
* The number 1, by definition, is not prime.
* a) Write a method that determines whether a number is prime.
* b) Use this method in an application that determines and displays all the prime numbers less than 10,000.
* How many numbers up to 10,000 do you have to test to ensure that you’ve found all the primes?
* c) Initially, you might think that n/2 is the upper limit for which you must test to see whether a number n is prime,
* but you need only go as high as the square root of n. Rewrite the program, and run it both ways.
*/
import java.util.Scanner;
public class PrimeNumberTest
{
/*
* // 基于2008年applet版本修改:
* 1. 改正了将1判定为质数的bug
* 2. 添加了注释
* 3. 取消了flag局部变量
*
*/
public static boolean IsPrime1(int argument)
{
if (argument ==1)
return false; //1既不是质数,也不是合数
else
{
for (int i=2;i<=Math.sqrt(argument);i++) //当要判断的数为2,3时,循环继续的条件不满足,循环体语句不会被执行,方法返回true
{
if (argument%i==0)
return false; //2到该整数的平方根取整之间出现了能被该整数整除的数字,判定为合数
}
return true; //运行到这里,说明不是合数,也不是1,即为质数
}
}
//以下为方法2,不是最优化的算法(循环继续的条件中的上限值未优化)
public static boolean IsPrime2(int argument)
{
if (argument ==1)
return false;
else
{
for (int i=2;i<argument;i++)
{
if (argument%i==0)
return false; //2到该整数的平方根取整之间出现了能被该整数整除的数字,判定为合数
}
return true; //运行到这里,说明不是合数,即为质数
}
}
public static void main(String[] args)
{
int size=0;
int count=0;
double duration=0.0;
Scanner input=new Scanner(System.in);
do {
count=0; //计数器清零
System.out.print("请输入上限(整数,输入-1退出):");
size=input.nextInt();
if(size==-1)
{System.out.print("已退出程序");
break;
}
System.out.print("请输入下限(整数,输入-1退出):");
int start=input.nextInt();
if(start==-1)
{System.out.print("已退出程序");
break;
}
System.out.print("请选择素数判定方法,1为优化方法,2为普通方法(整数,输入-1退出):");
int methodUsed=input.nextInt();
if(methodUsed==-1)
{System.out.print("已退出程序");
break;
}
else{
if (methodUsed == 1)
{
long beginTime=System.currentTimeMillis();
for (int i=start;i<=size;i++){
if (IsPrime1(i)){
System.out.printf("%d\t",i);
count++;
if (count%12==0)
System.out.println();
}
}
long endTime=System.currentTimeMillis();
duration=(double)(endTime-beginTime)/1000;
System.out.printf("\n%d至%d之间的素数共有以上%d个,方法1共用时%.2f秒。\n\n",start,size,count,duration);
}
else if (methodUsed == 2)
{
long beginTime=System.currentTimeMillis();
for (int i=start;i<=size;i++){
if (IsPrime2(i)){
System.out.printf("%d\t",i);
count++;
if (count%10==0)
System.out.println();
}
}
long endTime=System.currentTimeMillis();
duration=(double)(endTime-beginTime)/1000;
System.out.printf("\n%d至%d之间的素数共有以上%d个,方法2共用时%.2f秒。\n\n",start,size,count,duration);
}
}
}
while (size!=-1);
input.close();
}
}
运行结果:
请输入上限(整数,输入-1退出):100000000 请输入下限(整数,输入-1退出):99999000 请选择素数判定方法,1为优化方法,2为普通方法(整数,输入-1退出):1 99999043 99999073 99999077 99999079 99999089 99999103 99999113 99999131 99999157 99999167 99999187 99999217 99999247 99999257 99999259 99999307 99999323 99999329 99999343 99999353 99999373 99999401 99999437 99999439 99999481 99999509 99999517 99999539 99999541 99999547 99999551 99999563 99999587 99999589 99999611 99999617 99999623 99999643 99999677 99999703 99999721 99999773 99999787 99999821 99999827 99999839 99999847 99999931 99999941 99999959 99999971 99999989 99999000至100000000之间的素数共有以上52个,方法1共用时0.02秒。
请输入上限(整数,输入-1退出):-1 已退出程序 |