頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


n次の近似曲線を求める(3)

n次の近似曲線を求める(2)
↑この続きだよ。前回作った配列をガウスジョルダン法で解いてみよう。
今回で「n次の近似曲線を求める」シリーズはおしまいだからね。

さっそくそのコードだけどこんな感じで。行列matrixArrayと答えをもらう用の構造体を渡しているよ。
-(void)calculateForMatrixArray:(double *)matrixArray Info:(CoefficientInfoD)coefficientInfo
{
    int nn = coefficientInfo.degree+1;//degree次関数近似

    for (int ii=0;ii < nn;ii++) {
	double temp1 = matrixArray[ii*nn+ii];
	for (int kk=ii;kk < nn+1;kk++) {
            matrixArray[kk*nn+ii] = matrixArray[kk*nn+ii]/temp1;
	}
		
	for(int jj=0;jj < nn;jj++) {
	    if (jj != ii) {
                temp1 = matrixArray[ii*nn+jj];
		for (int kk=ii;kk < nn+1;kk++) {
                    matrixArray[kk*nn+jj] = matrixArray[kk*nn+jj] - temp1 * matrixArray[kk*nn+ii];
		}
	    }
	}
    }
	
    //答えを入れる
    for(int ii=0;ii < nn;ii++) {
        coefficientInfo.coe[ii] = matrixArray[nn*nn+ii];
    }
}
ここで出てくる構造体CoefficientInfoDはこんなの。予め宣言しておかないとだめだね。
typedef struct {
    int degree;//degree次の関数で近似
    double *coe;
} CoefficientInfoD;
これで近似曲線を描くのに必要な係数を求めることができるはずだよ。
うまくいかなかったら、俺のコードが間違っているか、必要なメモリを確保していないとか、、、
ガウスジョルダン法の関数部分なら一番手っ取り早いのは自分で答えがわかっている連立方程式を作っておいて解かせるって方法だと思うよ。

とにかくこれを使って近似曲線になっているか試しに描いてみよう。

5次関数で近似
↑これは5次関数で近似したもの。それらしく近似曲線になってるけど、こりゃお客様には出せませんって感じだよね。

9次関数で近似
↑これは9次の場合なんだ。これだといい感じだね!

ちなみに上のコードは倍精度(double)で計算してるけど、実は最初は単精度(float)でやってたんだ。単精度でも二次、三次くらいなら問題なかったんだけど高次になるとどうも怪しくなってきたんだ。さすがにべき乗の計算をするのに単精度だと具合悪いのかもね、ってことで倍精度にしたらその不具合解消されたんだよ。

ただ関数を高次にすればするほどどんどんオリジナルの点との差は確かに小さくなっていくんだけど、それはそれでややこしいことが起きるんだ。
例えばこんなの。

25次関数で近似
↑これは25次で計算したものなんだけど、、、そりゃそうだよね、高次の関数で各点にどんどん近づいていくからそれを満たそうとするとこういうことになるわけだよね。

でも実際にはスムーズな曲線でびゅーっとやって欲しいわけで、どのようにして、どのくらいの次数にすればいいのかってのはまた難しいところだからよーく考えるんだよ!

なんてえらそうに言ってるけど、どうしたらいいのかよくわかってないんだ。へへっ!

<< コードを使い回す時のマイルール   TopPage  n次の近似曲線を求める(2) >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/702-c4ea5d14




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad