Discussion:
[問題] 作出可判斷質數的程式
(时间太久无法回复)
ㄟ死ㄎㄟ吐狙
2006-09-28 05:18:45 UTC
Permalink
今天老師讓我們這些JAVA初學者練習兩題
一題是較簡單的
讓我們用JAVA寫出個程式能從1加到100的值給算出來
另一題是
希望我們能寫個程式
讓電腦自行把1到200中
所有的質數給挑出來
小弟不才
雖然有想到以前老師教的判斷質數的方法(就是把那個數先開根號,然後去比較)
可是重點來了
這部分我不會寫
不知道該如何編譯比較好
不知板上各位大大有無更好的方法可供參考
或者是真的很厲害
能把以前國中老師教的這種判斷方法給寫出來...

問問大家了
謝謝

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.228.190.67
t***@kkcity.com.tw
2006-09-28 15:27:08 UTC
Permalink
Post by ㄟ死ㄎㄟ吐狙
今天老師讓我們這些JAVA初學者練習兩題
一題是較簡單的
讓我們用JAVA寫出個程式能從1加到100的值給算出來
另一題是
希望我們能寫個程式
讓電腦自行把1到200中
所有的質數給挑出來
小弟不才
雖然有想到以前老師教的判斷質數的方法(就是把那個數先開根號,然後去比較)
可是重點來了
這部分我不會寫
不知道該如何編譯比較好
不知板上各位大大有無更好的方法可供參考
或者是真的很厲害
能把以前國中老師教的這種判斷方法給寫出來...
問問大家了
謝謝
往前找找之前的文章,這算是月經題了....

不過....要會寫程式,真的要懂得去思考....不然程式永遠寫不出來。

你老師還算仁慈,至少還告訴你們要開根號,我以前老師就很殘忍,第一
個作業就是要我們算出第一萬個質數的值是多少,而且是要在一分鐘內,
(當時的機器是Pentium100,用暴力法找到一定要花十分鐘以上),一個星
期後的小考要上機考....寫不出來的話,後面就可以不用來了....但除此
之外就沒任何提示了。

既然已經知道要開根號,所以,
首先,要知道怎麼寫開根號的語法,
再來就是如何寫一個迴圈,for與while任選一個,
再用if-else去作比較,如何確定一個數是質數,

最後再用這種方法,去跑1到200的迴圈找出質數....如此而已....不難的啦
--
┌─────◆KKCITY◆─────┐  KKBOX◤歌名╱歌手╱歌詞╱專輯◢搜尋 
│ bbs.kkcity.com.tw │   ★ http://www.kkbox.com.tw ★
└──《From:61.62.107.41 》──┘ 超過80家唱片公司合法授權 音樂盡情下載
--
n/a
2006-09-28 07:09:01 UTC
Permalink
笨方法,求某數是不是質數
從2開始除,可以整除表示不是質數

bool test( int n )
{
for ( int i = 2; i < n; i++ )
{
if ( ( i % n ) == 0 ) return false;
}
return true;
}

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 210.60.29.254
骨頭
2006-09-28 11:55:25 UTC
Permalink
※ 引述《***@kkcity.com.tw ( )》之銘言:
: ※ 引述《***@ptt.cc (ㄟ死ㄎㄟ吐狙)》之銘言:
: 往前找找之前的文章,這算是月經題了....
: 不過....要會寫程式,真的要懂得去思考....不然程式永遠寫不出來。
: 你老師還算仁慈,至少還告訴你們要開根號,我以前老師就很殘忍,第一
: 個作業就是要我們算出第一萬個質數的值是多少,而且是要在一分鐘內,
: (當時的機器是Pentium100,用暴力法找到一定要花十分鐘以上),一個星
: 期後的小考要上機考....寫不出來的話,後面就可以不用來了....但除此
: 之外就沒任何提示了。

一萬個質數要怎麼找會比較有效率啊 真好奇XD

動態規劃法好像可以派的上用場? (將找到的質數記錄下來再做處理...)
不過怎麼想好像還是有點累贅


我的作法是 除2以外取奇數 (因為偶數會被2整除:P)

待測數是從小到大開始 將已歸類為質數的記錄在list中

用待測數 去比對list中比待測數開根號小的質數是否能整除


主要的時間消耗應該是在比對質數陣列中
這部份不曉得有沒有更好的方法 :P (比開根號還好用的)


這時間複雜度好像也不是那麼好算 XD

--
 String temp="relax"; | Life just like programing
 while(buringlife) String.forgot(temp); | to be right or wrong
 while(sleeping) brain.setMemoryOut(); | need not to say
 stack.push(life.running); | the complier will
 stack.push(scouting.buck()); | answer your life
 stack.push(bowling.pratice()); | Bone everything

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.134.27.68
※ 編輯: TonyQ 來自: 220.134.27.68 (09/29 03:55)
愚者
2006-09-28 17:22:41 UTC
Permalink
※ 引述《TonyQ (骨頭)》之銘言:
: ※ 引述《***@kkcity.com.tw ( )》之銘言:
: : 往前找找之前的文章,這算是月經題了....
: : 不過....要會寫程式,真的要懂得去思考....不然程式永遠寫不出來。
: : 你老師還算仁慈,至少還告訴你們要開根號,我以前老師就很殘忍,第一
: : 個作業就是要我們算出第一萬個質數的值是多少,而且是要在一分鐘內,
: : (當時的機器是Pentium100,用暴力法找到一定要花十分鐘以上),一個星
: : 期後的小考要上機考....寫不出來的話,後面就可以不用來了....但除此
: : 之外就沒任何提示了。
: 一萬個質數要怎麼找會比較有效率啊 真好奇XD
: 動態規劃法好像可以派的上用場? (將找到的質數記錄下來再做處理...)
: 不過怎麼想好像還是有點累贅
: 我的作法是 除2以外取奇數 (因為偶數會被2整除:P)
: 待測數是從小到大開始 將已歸類為質數的記錄在list中
: 用待測數 去比對list中比待測數開根號小的質數是否能整除
: 主要的時間消耗應該是在比對質數陣列中
: 這部份不曉得有沒有更好的方法 :P (比開根號還好用的)
: 這時間複雜度好像也不是那麼好算 XD

另一個簡單的作法就是動態規劃啊:)

http://mathworld.wolfram.com/PrimeFactorization.html

看看第一張表 :P

ex. 求1~200中為質數者

N = {4, 5, 6, 7, 8, 9, ................. 200}

DP_TABLE = {2, 3} <-- 放質數

for each in N
for each in DP_TABLE
if N.e % DP.e == 0
// not prime
del N.e in N
end if
if find prime, add to DP_TABLE

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 163.26.34.213
t***@kkcity.com.tw
2006-09-29 02:05:46 UTC
Permalink
Post by 愚者
※ 引述《TonyQ (骨頭)》之銘言:
: 一萬個質數要怎麼找會比較有效率啊 真好奇XD
: 動態規劃法好像可以派的上用場? (將找到的質數記錄下來再做處理...)
: 不過怎麼想好像還是有點累贅
: 我的作法是 除2以外取奇數 (因為偶數會被2整除:P)
: 待測數是從小到大開始 將已歸類為質數的記錄在list中
: 用待測數 去比對list中比待測數開根號小的質數是否能整除
: 主要的時間消耗應該是在比對質數陣列中
: 這部份不曉得有沒有更好的方法 :P (比開根號還好用的)
: 這時間複雜度好像也不是那麼好算 XD
另一個簡單的作法就是動態規劃啊:)
http://mathworld.wolfram.com/PrimeFactorization.html
看看第一張表 :P
ex. 求1~200中為質數者
N = {4, 5, 6, 7, 8, 9, ................. 200}
DP_TABLE = {2, 3} <-- 放質數
for each in N
for each in DP_TABLE
if N.e % DP.e == 0
// not prime
del N.e in N
end if
if find prime, add to DP_TABLE
不過後來等到上機考過了之後,大家開始拼速度....
其實只要用開根號去比對,速度就快了十倍,所以只要用這方法在P100的機器上
跑就一定跑得進一分鐘內。
再來就衍生出第二種方法,就是qrtt1大大講的「動態規劃」,當時我們也不知道
這叫動態規劃,只是覺得這也是可行的方法,畢竟光是2跟3就可以去掉5/6的數量
了,不過,因為我們的題目是「找出第十萬個質數」而非從「十萬個質數找出所有
質數」,等到數字很大時,其實速度會被Delay(記得喲!時空背景是P100喲!)
後來,最後的大絕招是啥?兩個放在一起用,就是開根號後用質數表去除....
這是我們最後想出來最快速的方法....之後就為第二個恐怖的上機考煩惱去了....

等到畢業後,聽說,是聽說喲!還有比這種方法更快速的方法....不過對當時我們
那群大一新生而言,最後大絕招已經快到一個境界了(最後程式碼不是我測的,),
只消幾秒鐘答案就跑出來了....再快還能多快?

--
┌─────◆KKCITY◆─────┐ ◢ ╱  想要成立班系社團站台嗎? 
│ bbs.kkcity.com.tw │ █▉ ─ KKcity即日起開放BBS站申請囉!
└──《From:61.62.107.41 》──┘ ◥ ╲ 免程式技術、硬體成本的選擇!!
--
骨頭
2006-09-28 20:36:46 UTC
Permalink
※ 引述《***@kkcity.com.tw ( )》之銘言:
: ※ 引述《***@ptt.cc (愚者)》之銘言:
: 不過後來等到上機考過了之後,大家開始拼速度....
: 其實只要用開根號去比對,速度就快了十倍,所以只要用這方法在P100的機器上
: 跑就一定跑得進一分鐘內。
: 再來就衍生出第二種方法,就是qrtt1大大講的「動態規劃」,當時我們也不知道
: 這叫動態規劃,只是覺得這也是可行的方法,畢竟光是2跟3就可以去掉5/6的數量
: 了,不過,因為我們的題目是「找出第十萬個質數」而非從「十萬個質數找出所有
: 質數」,等到數字很大時,其實速度會被Delay(記得喲!時空背景是P100喲!)
: 後來,最後的大絕招是啥?兩個放在一起用,就是開根號後用質數表去除....
: 這是我們最後想出來最快速的方法....之後就為第二個恐怖的上機考煩惱去了....
: 等到畢業後,聽說,是聽說喲!還有比這種方法更快速的方法....不過對當時我們
: 那群大一新生而言,最後大絕招已經快到一個境界了(最後程式碼不是我測的,),
: 只消幾秒鐘答案就跑出來了....再快還能多快?

動態規劃(Dynamic Programming)的簡介 , 一個用空間換取時間的演算法.
http://zh.wikipedia.org/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92

XD 吾所見與汝戚戚焉


我覺得還能加快的地方,應該是num的值域啦。比方說我們知道2是值數,
就在一開始的時候就不把偶數列進去一樣,不過不是很容易...XD


底下是我的code

LinkedList<Integer> list=new LinkedList<Integer>();
boolean check;
for(int i=0,num=2;i<10000;){
check=true;
for(int j=0;j<list.size()&&
Math.sqrt(num)>=list.get(j);j++){
if(num%list.get(j)==0){
check=false;
}
}
if(check){
list.add(num);
System.out.print(list.get(i)+" ");
i++;
}
if(num%2==0){
num++;
}else{
num+=2;
}
}

--
 String temp="relax"; | Life just like programing
 while(buringlife) String.forgot(temp); | to be right or wrong
 while(sleeping) brain.setMemoryOut(); | need not to say
 stack.push(life.running); | the complier will
 stack.push(scouting.buck()); | answer your life
 stack.push(bowling.pratice()); | Bone everything

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.134.27.68
小安
2006-09-28 21:31:13 UTC
Permalink
※ 引述《TonyQ (骨頭)》之銘言:
: 一萬個質數要怎麼找會比較有效率啊 真好奇XD

幾年前討論區也討論過質數問題
那時候有看到一個建立質數表的方法

如果是一萬個質數的話,
就先建立長度 10000 的 boolean 陣列 (當然用 bit 的方式也可以)
並初始化為 true

然後索引 i 從 2 開始,一但發現 true 即代表 i 為質數,
接著把所有小於 10000 的 i 的倍數都設成 false...依此類推

這就是建立質數表了,
比起對每個數檢查是否為質數應該會快不少

如果再配合 2 的倍數的處理,應該又可以省下一點時間

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.126.173.31
小安
2006-09-29 16:13:36 UTC
Permalink
【 在 ***@bbs.wretch.cc () 的大作中提到: 】
: 試試這個 i從2開始 一直到根號n
: for(i=2;i<=sqrt(n);i++) {
: if(n%i) {
: system.out.println(n+"is prime number!");
: i=n;
: }
: }
: 那它的時間複雜度降到n^(1/2)

對一個數檢查是否為質數是只需 n^(1/2) 沒錯
但是這裡應該用檢查 n 個數來比較才是,所以應該是 n^(3/2)

而你所提的演算法其實是可以改進的,
只要把目前的 for 迴圈的 i 改成只跑已經算出來的質數 (當然,同樣是小於 sqrt(n) )
也就是前面 TonyQ 所提過的方法

我所提的方法其實也是這樣,雖然看起來是 O(n^2)
但其實與 TonyQ 的運算方式差不多
而在一些瑣碎的地方應該是更為精簡 (這部分就純粹只是個人觀點了)
--
NPDA - Non-deterministic PushDown Automata
(不確定是否推倒自動機)
DPDA - Deterministic PushDown Automata
(確定會推倒自動機)

得証: DPDA 效率比較高

※ 來源:‧資訊傳奇 inf.csie.thu.edu.tw‧[FROM: 59-126-173-31.HINET-IP.hinet.n]
!H45
2006-09-29 10:26:17 UTC
Permalink
※ 引述《***@inf.csie.thu.edu.tw (小安)》之銘言:
: 【 在 ***@bbs.wretch.cc () 的大作中提到: 】
: : 試試這個 i從2開始 一直到根號n
: : for(i=2;i<=sqrt(n);i++) {
: : if(n%i) {
: : system.out.println(n+"is prime number!");
: : i=n;
: : }
: : }
: : 那它的時間複雜度降到n^(1/2)
: 對一個數檢查是否為質數是只需 n^(1/2) 沒錯
: 但是這裡應該用檢查 n 個數來比較才是,所以應該是 n^(3/2)
: 而你所提的演算法其實是可以改進的,
: 只要把目前的 for 迴圈的 i 改成只跑已經算出來的質數 (當然,同樣是小於 sqrt(n) )
: 也就是前面 TonyQ 所提過的方法
: 我所提的方法其實也是這樣,雖然看起來是 O(n^2)
: 但其實與 TonyQ 的運算方式差不多
: 而在一些瑣碎的地方應該是更為精簡 (這部分就純粹只是個人觀點了)

看看這個連結吧: http://primes.utm.edu/prove/prove4_3.html

對一個數檢查是否為質數並不需要到 O(n^(1/2)) 喔

這個連結指出 O((log n)^12 f(log log n)) where f is a polynomial.

所以求質數的方法還可以再改進的

至少目前為止 po 出來的程式碼都沒有我所記錄過的 code 還快 @_@

--

是不是該移駕到 prob_solve 板討論了呢 XD

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.115.205.85

继续阅读narkive:
Loading...