Re: [問題] 多項式 跑出一堆不預期的數字..

看板C_and_CPP作者 (藍影)時間13年前 (2011/07/14 23:30), 編輯推噓4(4017)
留言21則, 3人參與, 最新討論串2/2 (看更多)
※ 引述《EarthQ (地球人崛起)》之銘言: 恕刪 架構我覺得真的很不好,我第一次看到有人用 struct 存 dfx_value 和 fx_value 有幾個問題也一起提出來 1. while(nroot<np) 你的 np 是你整個方程式的「最大冪次」,假設是 10 冪次, 不代表剛好有 10 個點 2. 步進問題 第 57 行裡面, x=x+1.0e-8; 你每次給的初始點是增 1E-8,且你收斂的 EPS 也是 1E-8, 我估就算找到了 10 個解,這十個解指向的都是同一個解。 3. 多項式算值 原本的寫法可能我比較看不懂,附上我的寫法.. double CalFx(double *Coef, int n, double xvalue) { int i; double ans=0; double pow_t=1; // 紀錄 x^i, i=[0,n] for(i=0; i<=n; ++i){ ans += pow_t*Coef[i]; pow_t*=xvalue; // pow_t = x^i } return ans; } 如果是 dfx 的話 for(i=1; i<=n; ++i){ // x^0 微分後省掉 ans += pow_t*Coef[i]*i; pow_t*=xvalue; // pow_t = x^i } 另外不建議設 struct 去存 fx 和 dfx 之值, 看了反而會誤解是二個點: double x, double y; ------------ 整體架構我認為最重大的缺失是在第 2 點,步進只用 1E-8, 通常在算非線性方程式要求根時,大致會這麼做: (1) 設上界值 a 與下界值 b ,注意 distance(a,b) 不能太大,但太小也沒意義。 通常我是設 distance(a,b) = 0.5~1.0,這是視問題大小而定。 (2) 利用勘根定理,若 f(a) * f(b) <=0,代表[a,b] 必「至少」存有一根; 若 f(a) * f(b) > 0,代表 [a,b] 可能沒有根 例外情況是,[a,b] 間的根是偶數個,將使得 f(a) * f(b) > 0 (3) 用勘根定理確定 [a,b] 間有根時,再用非線性解法 (你的是牛頓法,其他的還有割線法、二分法、定點回路法等) 去求 [a,b] 間存在之根其值為何。 牛頓法去做大概只有二個前題:可微、連續, (用牛頓法求不出來的 連續、可微函式 目前只有一種,不過不是你這種函式), 但我認為應先用勘根定理,把求解區間縮小為佳。 ------ 以上,供參閱。 -- YouLoveMe() ? LetItBe() : LetMeFree(); -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.78.41

07/14 23:31, , 1F
orz .. 我動作太慢了..
07/14 23:31, 1F

07/14 23:34, , 2F
別灰心T大 明天他可能就會看到了
07/14 23:34, 2F

07/14 23:36, , 3F
不過dfx應該可以跟fx合併於一個for
07/14 23:36, 3F

07/14 23:42, , 4F
對,可以合併在一個 for.
07/14 23:42, 4F
那段副函式我會設計成這樣 double Cal(double *Coef, int n, double xvalue) { int i; double fx=Coef[0], dfx=0; double pow_t=1; // 紀錄 x^i, i=[0,n] for(i=1; i<=n; ++i){ dfx += pow_t*Coef[i]*i; pow_t*=xvalue; // pow_t = x^i fx += pow_t*Coef[i]; } return fx/dfx; } 的確用一個 loop 就算出來, 因收斂條件用到的是 f(x)/f'(x), 也可以直接傳回 delta 也沒問題, return (x-fx/dfx); 這樣就可以當作是下一個 x 之迭代,更方便, 實在沒必要還要多設一個 struct 還是引數再用二個 int *fx , int *dfx。 ※ 編輯: tropical72 來自: 180.177.78.41 (07/15 00:09)

07/16 11:51, , 5F
先謝謝啦!
07/16 11:51, 5F

07/16 11:52, , 6F
第一個問題阿 我做出來是每個解都有找到ㄟ 我想是我有設
07/16 11:52, 6F

07/16 11:53, , 7F
設一個sum 把每一次找到的解都先去掉 所以應該不會重復吧
07/16 11:53, 7F

07/16 11:54, , 8F
說錯== 是第二個問題 然後第一個 因為有把找到的除掉了
07/16 11:54, 8F

07/16 11:55, , 9F
所以雖然可能沒10個點 但不會有問題
07/16 11:55, 9F

07/16 11:55, , 10F
((應該是吧 照我對教授說得的了解..
07/16 11:55, 10F

07/16 11:57, , 11F
然後學起來了 用struct 可能會照成誤會 ..
07/16 11:57, 11F

07/16 11:59, , 12F
謝謝啦!! 下次會加入勘根
07/16 11:59, 12F

07/16 14:07, , 13F
我想補的是,我真的確定,你求出來的根是錯的
07/16 14:07, 13F

07/16 14:07, , 14F
考慮 f(x) = (x-2.31)(x+1.78)(x-4.95),展開變
07/16 14:07, 14F

07/16 14:07, , 15F
= x^3 - 5.48x^2 - 1.4883x + 20.394828
07/16 14:07, 15F

07/16 14:08, , 16F
你拿這個去輸入,答案是錯的.
07/16 14:08, 16F

07/16 14:08, , 17F
不是浮點數誤差那種,是差很大的那種.
07/16 14:08, 17F

07/16 21:00, , 18F
恩恩恩 得到 2.313838 -1.781504 4.94766 這樣誤差算很
07/16 21:00, 18F

07/16 21:01, , 19F
大嗎?
07/16 21:01, 19F

07/16 21:02, , 20F
那我該加入些什麼呢? ((煩請不吝賜教 :)
07/16 21:02, 20F

07/17 17:08, , 21F
我覺得不要有sum 就會比較好...
07/17 17:08, 21F
文章代碼(AID): #1E7mkIG2 (C_and_CPP)
文章代碼(AID): #1E7mkIG2 (C_and_CPP)