傳統算法:
逐個判斷是不是素數,有的簡單優化就是在判斷的時候使用的上限是平方根,當然每個數字還是要逐個判斷,使用的是i++的形式
這裏使用的是篩法:
並不是逐個判斷,篩法的定義爲:
先把N個自然數按次序排列起來。1不是質數,也不是合數,要劃去。第二個數2是質數留下來,
而把2後面所有能被2整除的數都劃去。2後面第一個沒劃去的數是3,把3留下,再把3後面所有能被3整除的數都劃去。
3後面第一個沒劃去的數是5,把5留下,再把5後面所有能被5整除的數都劃去。
c這樣一直做下去,就會把不超過N的全部合數都篩掉,留下的就是不超過N的全部質數。因爲希臘人是把數寫在塗臘的板上,
每要劃去一個數,就在上面記以小點,尋求質數的工作完畢後,這許多小點就像一個篩子,
所以就把埃拉託斯特尼的方法叫做“埃拉託斯特尼篩法”,簡稱“篩法”。
(另一種解釋是當時的數寫在紙草上,每要劃去一個數,就把這個數挖去,尋求質數的工作完畢後,這許多小洞就像一個篩子。
並不逐個判斷:首先:偶數一定不是素數,所以我循環的時候採用的不是i++,而是i每次加2,判斷是否是素數的似乎也不是將2到本身(或是平方根)的逐個相除看是否能夠除盡來運算,而是篩選法的方式,每個數因爲在循環的時候就確定了一定是基數,所以判斷只需要是小於它的基數,而不是逐個,當然也就可以改良爲小於它平方根來判斷。不知道是不是最優,如果有更好的方法,希望能貼出來吧sincerely...
summary:判斷是否是素數的時候上限,使用的是平方根或者是本身對於效率改進並不會有太大改進。因爲:平方根屬於底層封裝,並不能很快得到結果。而簡單的循環則是速度極快的,相比循環次數增加但是計算平方根的時間增加,所以其實效率不會有太大的改善
代碼:
package algorithm;
/**
* 2~2000的所有素數,要求效率儘可能高
* @author cilen
*
*/
public class PrimeTest {
public static void main(String[] args) {
long t = System.currentTimeMillis();
int count=1;
System.out.println(2);//2是已知不需要參與判斷
for(int i=3;i<2000;)
{
if(isPrime(i))
{
count++;
System.out.println(i);
}
i=i+2;//每次加2,不是加1
}
System.out.println("總共的個數爲:"+count);
t = System.currentTimeMillis()-t;
System.out.println("經歷的時間爲:"+t);
}
public static boolean isPrime(int n )
{
for(int j=3;j<n;)
//int max=(int)Math.floor(Math.sqrt(n));下面的Math.sqrt(n)可以被替換爲這個max
// for(int j=3;j<=Math.sqrt(n);)--這裏是<=,如果少了等於,會出現能開平方根的數被打印
{
if(n%j==0)
{
return false;
}
j=j+2;
}
return true;
}
}
具體哪個是素數就不打印了總共的個數爲:303
經歷的時間爲:13
傳統的方法:
package algorithm;
public class Demo {
public static void main(String[] args)
{
long t = System.currentTimeMillis();
int count =0;
int i,j,k=0;
for(i=2;i<=2000;i++)
{
for(j=2;j<=i/2;j++)
if(i%j==0)break;
if(j>i/2)
{
System.out.println(i);
count++;
}
}
t = System.currentTimeMillis()-t;
System.out.println("總共個數:"+count);
System.out.println("經歷的時間爲:"+t);
}
}
得出:
總共個數:303
經歷的時間爲:19
可見:使用篩選法的時間能節省約:1/3
希望得到更好的算法或者改進,待mark...