• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:a*(1-exp(-bx))+cの近似の方法)

データの近似に関する方法とライブラリについて

このQ&Aのポイント
  • データを近似するための方法やライブラリについて検討しています。
  • 現在、市販のグラフソフトを使用してデータの近似曲線を得ていますが、手間がかかります。
  • どのような方法が適切であり、ソフト内に組み込むことができるのかご教示いただけますか。

質問者が選んだベストアンサー

  • ベストアンサー
回答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; }

R_ASO
質問者

お礼

どうにか最小プログラムで実現できました。 ソフトに組み込んでみます。 本当にありがとうございました。 処理が重くなったときはそのときにほかの方法を考えます。 gnuplotって便利ですね。 gnuplotについてはこれから勉強していきます。

その他の回答 (2)

回答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#9.3 * 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; }

R_ASO
質問者

お礼

gnuplotはきいたことがありましたが使ったことがなかったので、 Cから使えるって発想がなかったです。 なんか簡単にできそうな気がしてきました。試してみます。

R_ASO
質問者

補足

gnuplotから得られたパラメータ"a","b","c"をCの変数に格納できるでしょうか。 gnuplotの"print a,b,c"の値が取得できれば解決しそうです。 fit.logから探すとなると処理が多くなるとなんとも気持ちがわるいので、 どうにかならないかなと思っています。 もしお分かりであれば、ご回答よろしくお願いいたします。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

近似式の形が決っているのなら、最小二乗法を使うのが一般的でしょう。 よく使われるものなので、解法の解説も多く、自分でプログラムを組んでもいいのです。 が、数値演算ライブラリに入っていることも多いので、それを使うと便利でしょう。 VCの例があるということで、こんなのはどうでしょうか http://www.mlab.ice.uec.ac.jp/~ej-sib/numerical/numerical_levmar.html

R_ASO
質問者

お礼

こんな便利なものがあるものですね。 勉強してみます。 ご回答ありがとうございました。

関連するQ&A