a*(1-exp(-bx))+cの近似の方法
x y
0 1.00
2 1.90
5 2.96
7 3.51
10 4.16
20 5.32
30 5.75
ある実験で上記のようなデータを取得しました。
ほとんどのyデータはx=30で3~30の間でほぼ飽和しています。
cは0~5の間を取ります。
現在市販のグラフソフトを使用してa*(1-exp(-bx))+cで近似曲線を得ています。
またデータを取るソフトはVCで作成しています。
データ数を毎回、グラフソフトを立ち上げてひとつづつ近似するのは
手間がかかってしまいますし、データ数も膨大になってきました。
そこで作成しているソフト内に組み込もうと思うのですが、どういった方法が適切なのかが
検討がつきません。方法またはそのようなことのできるライブラリなどご存知であればご回答よろしくお願いします。
No.1
- 回答日時:
近似式の形が決っているのなら、最小二乗法を使うのが一般的でしょう。
よく使われるものなので、解法の解説も多く、自分でプログラムを組んでもいいのです。
が、数値演算ライブラリに入っていることも多いので、それを使うと便利でしょう。
VCの例があるということで、こんなのはどうでしょうか
http://www.mlab.ice.uec.ac.jp/~ej-sib/numerical/ …
No.2
- 回答日時:
当方、Windows のVCではないMac OSX ですが、参考になれば幸いです。
プログラムは、日々データを加えて図化してはその傾向を視覚確認することを簡略化するのに重宝します。Windows版GnuPlotはMac OSXと使い方に細かな違いがあると思われますので「gnuplot>」のコマンドラインからfprintf(gp, ...) の内容を実行して確認してみてください。
/* Gcc on Mac OSX
* See http://t16web.lanl.gov/Kawano/gnuplot/misc2.html …
* file name: raso.c
* compile: gcc raso.c
* execution: ./a.out
*/
#include <stdio.h>
#include <stdlib.h>//exit()
#define FILE_NAME "jikken.dat"
#define GP_LOGFILE "fit.log"
#define SIZE 128
#define input_str(c,x) {printf(c); fgets(x, SIZE, stdin);}
int main(void) {
int i;
char buff[SIZE];
FILE *fp, *gp;
input_str("Data input? (y/n) ", buff);
if (*buff == 'y' || *buff == 'Y') {
if ((fp = fopen(FILE_NAME, "a+")) == NULL) {
perror("fopen");
exit(1);
}
printf("\tData inputting and curve fitting.\n");
printf("\tLoop end: Push [return] key only.\n");
input_str("Input comment: ", buff);
fprintf(fp, "\n");
fprintf(fp, "# %s", buff);
i = 1;
printf("%d_ ", i);
input_str("x y: ", buff);
while (*buff != '\n') {
fprintf(fp, "%s", buff);
i++;
printf("%d_ ", i);
input_str("x y: ", buff);
}
fclose(fp);
} else {
if (!(*buff == 'n' || *buff == 'N')) {
printf("select y/n error.\n");
exit(1);
}
if ((fp = fopen(FILE_NAME, "r")) == NULL) {
perror("fopen");
exit(1);
}
printf("\tCurve fitting only.\n");
fclose(fp);
}
// GnuPlot
if ((gp = popen("gnuplot", "w")) == NULL) {
perror("popen");
exit(1);
}
// 既存fit.logファイルの削除
sprintf(buff, "rm %s\n", GP_LOGFILE);
system(buff);
// GnuPlot の実行
fprintf(gp, "f(x)=a*(1-exp(-b*x))+c \n");
fprintf(gp, "a=5; b=0.5; c=1 \n");
fprintf(gp, "fit f(x) '%s' via a,b,c \n", FILE_NAME);
fprintf(gp, "set title 'An example' \n");
fprintf(gp, "set xlabel 'X' \n");
fprintf(gp, "set ylabel 'Y' \n");
fprintf(gp, "plot f(x) with lines title 'a*(1-exp(-bx))+c', '%s' with points \n", FILE_NAME);
pclose(gp);
// 新fit.logファイルの閲覧
sprintf(buff, "more %s\n", GP_LOGFILE);
system(buff);
return 0;
}
この回答への補足
gnuplotから得られたパラメータ"a","b","c"をCの変数に格納できるでしょうか。
gnuplotの"print a,b,c"の値が取得できれば解決しそうです。
fit.logから探すとなると処理が多くなるとなんとも気持ちがわるいので、
どうにかならないかなと思っています。
もしお分かりであれば、ご回答よろしくお願いいたします。
gnuplotはきいたことがありましたが使ったことがなかったので、
Cから使えるって発想がなかったです。
なんか簡単にできそうな気がしてきました。試してみます。
No.3ベストアンサー
- 回答日時:
GnuPlotは独立したひとつのプログラムですから、定数a,b,c を直接利用することはできません。
fit.logファイルを読むしかありません。ソースは2000字制限で全部を載せることができないため、#2の「 input_str();if () else 」文をコピペしてください。
/* Gcc on Mac OSX
* file name: r_aso.c
* compile: gcc r_aso.c
* execution: ./a.out
*/
#include <stdio.h>
#include <stdlib.h>//exit(),system()
#include <string.h>//strtok(),strstr()
#define SIZE 128
#define FILE_NAME "jikken.dat"
#define GP_LOGFILE "fit.log"
#define SPC " "
#define KEYWORD "+/-"
#define input_str(c,x) {printf(c);fgets(x,SIZE,stdin);}
#define set_token(v,x) {strtok(x,SPC);strtok(NULL,SPC);v=atof(strtok(NULL,SPC));}
int main(void) {
int i;
char buff[SIZE];
FILE *fp,*gp;
double a,b,c;
/*ここに
input_str("Data input? (y/n) ",buff);
if (*buff=='y' || *buff=='Y') {
....
をコピペのこと。 */
// ***** GnuPlot *****
if ((gp=popen("gnuplot","w"))==NULL) {
perror("popen");
exit(1);
}
// 既存fit.logファイルの削除
sprintf(buff,"rm %s\n",GP_LOGFILE);
system(buff);
// fit.log の作成
fprintf(gp,"f(x)=a*(1-exp(-b*x))+c \n");
fprintf(gp,"a=5;b=0.1;c=1 \n");
fprintf(gp,"fit f(x) '%s' via a,b,c \n",FILE_NAME);
pclose(gp);//←ここでいったん GnuPlotを閉じる
//定数a,b,c の読み取り
if ((fp=fopen(GP_LOGFILE,"r"))==NULL) {
perror("fopen(GP_LOGFILE)");
exit(1);
}
fgets(buff,SIZE,fp);
while (strstr(buff,KEYWORD)==NULL){
fgets(buff,SIZE,fp);
}
set_token(a,buff);
fgets(buff,SIZE,fp);
set_token(b,buff);
fgets(buff,SIZE,fp);
set_token(c,buff);
fclose(fp);
sprintf(buff,"%f*(1-exp(-%f*x))+%f",a,b,c);
//GnuPlotによる描画
gp=popen("gnuplot","w");
fprintf(gp,"set xrange [0:40] \n");
fprintf(gp,"set yrange [0:8] \n");
fprintf(gp,"set title 'An example' \n");
fprintf(gp,"set xlabel 'X' \n");
fprintf(gp,"set ylabel 'f(x)' \n");
fprintf(gp,"plot '%s' with points pointtype 6 pointsize 1.5 \n",FILE_NAME);
fprintf(gp,"f(x)=%s \n", buff);
fprintf(gp,"replot f(x) with lines title 'f(x)= %s' \n", buff);
pclose(gp);
//結果のターミナル出力
printf("\n");
printf("GnuPlot fitting result:\n");
printf("\tf(x) = %s\n", buff);
return 0;
}
どうにか最小プログラムで実現できました。
ソフトに組み込んでみます。
本当にありがとうございました。
処理が重くなったときはそのときにほかの方法を考えます。
gnuplotって便利ですね。
gnuplotについてはこれから勉強していきます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 確定申告 eTaxを利用しての確定申告 2 2023/03/04 21:12
- 確定申告 住宅ローン控除 e-taxソフトでの申請について 2 2023/01/21 20:05
- CAD・DTP JWW-CADでDXF変換後の線が連動して消える 2 2023/01/13 11:09
- ドライブ・ストレージ SSDを追加したら昔のHDDがおかしくなった 4 2023/03/23 13:25
- Excel(エクセル) VBA : スクレイピングできない 4 2023/05/12 22:26
- その他(IT・Webサービス) iPhone内で削除してしまった写真の復元方法 2 2023/07/15 12:30
- Windows 10 Windows10搭載の画面録画 容量を小さくする方法ありますか? 3 2022/06/21 09:45
- ソフトウェア データ入力のインターフェースについて 2 2022/09/27 09:07
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- 画像編集・動画編集・音楽編集 動画をディスク作成すると画像が乱れる。 4 2022/06/24 07:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エラーがわかりません、、
-
ファイルへの書込み処理が異常...
-
c言語 ファイルから数字を読み...
-
ファイルに行番号を追加
-
c言語でのfscanfについて
-
ガンマ変換 C言語でプログラ...
-
ファイルの特定行の抽出
-
ファイル読み込み EOF 判定
-
Cで文字列の分割
-
2÷3などの余りについて
-
C言語で%を使わない余りの出し方
-
比較回数と交換回数表示について
-
信頼区間の1.96や1.65ってどこ...
-
nCmの関数
-
複数桁10進数の*桁目だけを抽出...
-
Notepad++の関数リスト表示の変...
-
C言語のfor文です。 繰り返しの...
-
break文でループを一気に抜ける...
-
正負を反転させて出力するプロ...
-
#define _CRT_SECURE_NO_WARNIN...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語でのfscanfについて
-
C言語でファイル読み書きを早く...
-
fopenでファイル名に、変数を使...
-
複数ファイルの同時読み込みの...
-
fgets( ) の返り値は何?
-
テキストファイル内に対して, ...
-
ファイルへの書込み処理が異常...
-
C言語にてXMLファイルから任意...
-
ファイル出力で改行を入れたい!
-
C言語でセグメンテーションエ...
-
エラーがわかりません、、
-
ガンマ変換 C言語でプログラ...
-
自己相関関数を求めるプログラ...
-
VisualStudioでのファイルの入...
-
同時にファイル読み込み 書き込み
-
c言語 ファイルから数字を読み...
-
大量の入力ファイルを扱うとき...
-
ファイルが読み込めない・・・
-
【C言語】ファイルを読み込んで...
-
a*(1-exp(-bx))+cの近似の方法
おすすめ情報