電子書籍の厳選無料作品が豊富!

現在、Visual C++ 2008 Express Editionを使用して下に示すようなダイアログベースの3次Spline補間のプログラムを作成しています。
各節点間を等分割するほうはできたのですが、各区間を同一刻み幅で算出するほうが、なかなかできません。
どこをどうしたらいいかがさっぱりです。
以下にプログラムの一部(各区間を同一刻み幅で計算する部分)を示しますので、教えてください。
わからない点は、dnの配列に入ってくる分割数が合っているときと少ないときがあることです。プログラムの後に使用した入力データと、dnの中身を参考までに掲載します。
============▼プログラムの一部===========
/* n:全点数(int), num:全節点数(int),xn,yn:節点(double型のarray),dX:全区間(xn[0]~xn[num-1])の刻み幅(double)
* dn[]:各区間の分割数(int),xx,yy:Spline補間による点(節点を含む,double),x計算された補間点のx座標(double)
Cub(double):3乗する関数,Sqr(double):2乗する関数,a[],b[],c[],d[]:3次Spline補間に用いる3次関数の各係数*/
//nの初期化
n =0;
//テキストボックスから刻み幅を取得
dX = double::Parse(DX->Text::get());
//各区間の分割数を計算し、全点数を求める
for(i=0;i<num-1;i++){
dn[i]=(int)((xn[i+1]-xn[i])/dX);
n +=dn[i];
}
//xx,yyを全点数+1(最後の節点を含むために+1をしている)で領域確保
xx=gcnew array<double>(n+1);
yy=gcnew array<double>(n+1);
//ループインデックスを初期化
i=0,j=0;
//補間点のx座標を求めながらy座標を算出
for(x=xn[0];x<=xn[num-1];x+=dX){
if(!((xn[j]<=x)&&(x<xn[j+1]))){
j++;
}
if(i>n+1){
break;
}
xx[i]=x;
yy[i]=a[j]*Cub(xx[i]-xn[j])+b[j]*Sqr(xx[i]-xn[j])+c[j]*(xx[i]-xn[j])+d[j];
i++;
}
=======▼入力データ(csvファイル)===========
xn yn
0.904 7.54
1.002 13.86
1.104 23.42
1.207 36.61
1.305 52.91
1.403 73.4
1.505 97
1.603 123
1.706 151.3
1.808 182.6
1.906 215.3
2.009 249.2
2.107 284.6
2.209 321.6
2.312 359
2.41 398.1
2.571 438.7
2.669 504.9
2.772 548.3
2.869 593
2.972 639
3.075 687
3.172 736
3.275 787
3.378 840
3.476 895
3.578 951
3.676 1011
3.779 1073
3.876 1136
3.979 1204
4.077 1276
4.18 1353
4.277 1440
4.38 1543
4.483 1762
4.585 2082
4.683 3445
4.786 5598
4.888 7120
4.991 8080

=======▼dnの中身===========
Excelでの計算値 プログラムでの計算値
---------------------------------------
98 97
102 102
103 102
98 97
98 98
102 101
98 98
103 102
102 102
98 97
103 102
98 98
102 101
103 102
98 98
161 161
98 97
103 102
97 97
103 102
103 103
97 96
103 102
103 103
98 97
102 101
98 98
103 102
97 96
103 103
98 97
103 102
97 97
103 102
103 102
102 102
98 97
103 102
102 102
103 102
上の表の右側はダイアログ上で、「区間間隔」をクリック(各ラジオボタンをクリックすると右横のテキストボックスが入力できるようになります。)してテキストボックスに0.001を入れた時の結果です。

「ダイアログベースの3次Spline補間の」の質問画像

A 回答 (1件)

intに変換する際の浮動小数点の誤差切捨てが発生しているのでしょう



for(i=0;i<num-1;i++){
  dn[i]=(int)Math::Round( (xn[i+1]-xn[i])/dX), 0 );
  n +=dn[i];
}
といった具合で丸めてみましょう

この回答への補足

あれから、ソ-スコードをいわれたとおり、修正したら無事できました。
 小数点のところで、誤差が出ていたなんて思いもよらなかったです。

本当にありがとうございました。

補足日時:2009/03/22 09:59
    • good
    • 0
この回答へのお礼

早速の回答ありがとうございます。

試してみます^^

お礼日時:2009/03/16 10:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!