看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《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
tropical72:orz .. 我動作太慢了.. 07/14 23:31
firejox:別灰心T大 明天他可能就會看到了 07/14 23:34
firejox:不過dfx應該可以跟fx合併於一個for 07/14 23:36
tropical72:對,可以合併在一個 for. 07/14 23:42
那段副函式我會設計成這樣 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)
EarthQ:先謝謝啦! 07/16 11:51
EarthQ:第一個問題阿 我做出來是每個解都有找到ㄟ 我想是我有設 07/16 11:52
EarthQ:設一個sum 把每一次找到的解都先去掉 所以應該不會重復吧 07/16 11:53
EarthQ:說錯== 是第二個問題 然後第一個 因為有把找到的除掉了 07/16 11:54
EarthQ:所以雖然可能沒10個點 但不會有問題 07/16 11:55
EarthQ:((應該是吧 照我對教授說得的了解.. 07/16 11:55
EarthQ:然後學起來了 用struct 可能會照成誤會 .. 07/16 11:57
EarthQ:謝謝啦!! 下次會加入勘根 07/16 11:59
tropical72:我想補的是,我真的確定,你求出來的根是錯的 07/16 14:07
tropical72:考慮 f(x) = (x-2.31)(x+1.78)(x-4.95),展開變 07/16 14:07
tropical72: = x^3 - 5.48x^2 - 1.4883x + 20.394828 07/16 14:07
tropical72:你拿這個去輸入,答案是錯的. 07/16 14:08
tropical72:不是浮點數誤差那種,是差很大的那種. 07/16 14:08
EarthQ:恩恩恩 得到 2.313838 -1.781504 4.94766 這樣誤差算很 07/16 21:00
EarthQ:大嗎? 07/16 21:01
EarthQ:那我該加入些什麼呢? ((煩請不吝賜教 :) 07/16 21:02
firejox:我覺得不要有sum 就會比較好... 07/17 17:08