學以致用——Java原始碼——任意範圍內的素數列印(Prime Number display)
看起來很簡單的一個程式,寫起來咋就這麼費時間呢?或許這就是所謂的知易行難吧。
當上限增加到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 已退出程式 |