- 輸出100以內的所有質數
- 質數:也叫素數,只能被1和他本身整除的自然數
- 最小的質數:2
方法一:效率很低
public class PrimeNumber {
public static void main(String[] args) {
}
@Test
public void method1(){
boolean b = true;
//遍歷100以內的自然數
for (int i = 2;i<=100;i++){
//j:被i除
for (int j=2;j<i;j++){
if (i % j == 0){ //%是求模運算,即2%10=2,10%2=0,10%3=1。
b = false;
}
}
if (b){
System.out.print(i+" ");
}
b = true;
}
}
}
輸出結果:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
實際上,上面的這種方法基本上是效率最低的。但因爲100實在是太小了,計算機的運算速度很快就能計算出100以內的質數,所以現在我們不改變算法的結構,把100換成10萬試試。
繼續方法一:
@Test
public void method1(){
//獲取當前時間距離1970-01-01 00:00:00的毫秒數
long start = System.currentTimeMillis();
boolean b = true;
//遍歷100以內的自然數
for (int i = 2;i<=100000;i++){
//j:被i去除
for (int j=2;j<i;j++){
if (i % j == 0){ //%是求模運算,即2%10=2,10%2=0,10%3=1。
b = false;
}
}
if (b){
System.out.print(i+" ");
}
b = true;
}
//獲取當前時間距離1970-01-01 00:00:00的毫秒數
long end = System.currentTimeMillis();
System.out.println("\n花費時間:"+(end-start)); //17704毫秒
}
運行結果:
用以上這種方法,輸出10萬以內的質數居然用了 17704毫秒,即17.7秒。在真實開發中。這麼慢的速度是絕對不允許的。
所以接下來對這個算法進行優化
方法二:
優化一:使用break更快地跳出循環
//對方法一進行優化
@Test
public void method2(){
//獲取當前時間距離1970-01-01 00:00:00的毫秒數
long start = System.currentTimeMillis();
//遍歷100以內的自然數
for (int i = 2;i<=100000;i++){
boolean b = true;
for (int j=2;j<i;j++){
if (i % j == 0){ //%是求模運算,即2%10=2,10%2=0,10%3=1。
b = false;
break;//優化一:只對本身非質數的自然數是有效的
}
}
if (b){
System.out.print(i+" ");
}
}
long end = System.currentTimeMillis();
System.out.println("\n花費時間:"+(end-start)); //優化一後:花費時間 1542ms
}
這一次,我在最內層的if語句中加入了 break;
這樣做的目的是讓非質數更快的跳出循環,比如for循環到了100,此時i=100,進入第二個for循環,此時j=2,100%2=0,於是馬上就break出了循環
運行結果:
可以看到,優化過後的速度立馬就上來了,用時1542毫秒。
方法三:
既然能對非質數進行優化,那是否可以對質數進行優化呢?當然可以
優化二:對本身是質數的自然數進行優化
@Test
public void method3(){
//獲取當前時間距離1970-01-01 00:00:00的毫秒數
long start = System.currentTimeMillis();
//遍歷100以內的自然數
for (int i = 2;i<=100000;i++){
boolean b = true;
//優化二:對本身是質數的自然數是有效的
for (int j=2;j<Math.sqrt(i);j++){
if (i % j == 0){ //%是求模運算,即2%10=2,10%2=0,10%3=1。
b = false;
}
}
if (b){
System.out.print(i+" ");
}
}
long end = System.currentTimeMillis();
System.out.println("\n花費時間:"+(end-start)); //優化二:208ms
}
爲什麼這樣優化我就不解釋了,大家可以看尚硅谷宋紅康老師講的這一課:http://www.gulixueyuan.com/course/309/task/7787/show
運行結果:
可以看到,現在運行結果相比優化一又快了,用了208ms。
方法四:
最終優化:把優化一和優化二結合。
public void method4(){
//獲取當前時間距離1970-01-01 00:00:00的毫秒數
long start = System.currentTimeMillis();
//遍歷100以內的自然數
for (int i = 2;i<=100000;i++){
boolean b = true;
//優化二:對本身是質數的自然數是有效的
for (int j=2;j<Math.sqrt(i);j++){
if (i % j == 0){ //%是求模運算,即2%10=2,10%2=0,10%3=1。
b = false;
break;//優化一:只對本身非質數的自然數是有效的
}
}
if (b){
System.out.print(i+" ");
}
}
long end = System.currentTimeMillis();
System.out.println("\n花費時間:"+(end-start)); //優化一加優化二:71ms
}
運行結果:
兩種算法優化結合在一起效果不言而喻,輸出10萬以內的質數僅用了71毫秒