• ベストアンサー

関数の掛け算を返す関数

いま関数の積分を行おうとしています. この積分を行う関数が double integral(double (*func)(double), double a, double b ) {    double ans;    .....    return ans; } となっていて,aからbまでfuncが指す関数を積分して結果を返します. 積分をさせる関数は double f1(double x) { return 3.0*x; } double f2(double x) { return x*x; } となっていて,同じようにg1, g2も用意します.(本当は関数が3つ4つあります.) 例えばf1を積分したいとき, int main() {    double ans = integral(f1, a, b);    printf("%f\n", ans); } ですよね. 自分で積分する関数を選ぶときは,ここに配列で場合分けをして double (*func_f[])(double)={f1, f2}; scanf("%d", &flag); /* flagに0~1を代入 */ ans = integral(func_f[flag], a, b); でいいと思います. さて,そこで本題なのですが, double (*func_f[])(double)={f1, f2}; double (*func_g[])(double)={g1, g2}; としておいて, scanf("%d", flag1); scanf("%d", flag2); func_f[flag1], func_g[flag2]; として関数を入力側から決定して, (例えばflag1=1, flag2=1,であったとして *func_f[1]=x*x *func_g[1]=5.0*x ならば) h(x)=(x*x)*(5.0*x)=5.0*x*x*x という関数を作って, h(x)を指すポインタを double (*h_ptr)(double) とすれば ans = integral(h_ptr, a, b); としたいのです. (f1*g2)を一つの関数としてh(x)=(f1*g2)(x)というように扱うことができればいいと思うのですが. integralの引数で,関数のポインタを2個にすると,汎用性が失われてしまうと思うので,できればそこは変えたくないです. どのようにすればよいのでしょうか? また,「考え方を変えればよい」などの意見も頂きたいです. 皆様,どうぞよろしくお願いします.

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

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.2

動的に関数を作り出すことは出来ませんから、有り得る組み合わせの関数、f1g1(),f1g2(),f2g1(),f2g2() を doube f1g1(double x) { return f1(x)*g1(x); } 等とすべて事前に定義しておく必要があります。 その上で、 double (*func[])(doube)={f1g1,f1g2,f2g1,f2g2}; として、 ans=integral(func[flag1*2+flag2],a,b);

yassan_yassan
質問者

お礼

回答ありがとうございます. f1g1を用意するときはどのようにするべきですか? 以下の方法では引数の数が異なってきてしまいますよね. double f1g1(double x, double (*f1)(double), double (*g1)(double)) { return f1(x)*g1(x); }

yassan_yassan
質問者

補足

すいません.勘違いしていました. 引数とか関係ないですね.失礼しました. この方法でいこうと思います. ありがとうございました.

その他の回答 (4)

  • SoHeart
  • ベストアンサー率50% (13/26)
回答No.5

#4ですが、今読み直して、誤解があってはまずいと思いかいてます。以下は自分自身が積分が不勉強なため作っては見たけど、自信ないです。間違ってるかもしれない。という意味で決してあなたのことをいってるのではないです。自分の場合コメントは次の行の説明として入れるのが習慣になってますので、もし誤解がありましたら、ご容赦願います。 ----------   /* 積分計算のつもりですが内容は微妙に    間違ってると思いますので、直してください。   */ ans = ans * ( ( F[i](b)*b ) - ( F[i](a)*a ) ); -----------

  • SoHeart
  • ベストアンサー率50% (13/26)
回答No.4

関数を配列にしてはどうでしょう。 double sub(double (*F[])(double), double a, double b) { double ans; int i; i = 0; ans = 1; while( F[i] != (void *)0 ){   /* 積分計算のつもりですが内容は微妙に    間違ってると思いますので、直してください。   */ ans = ans * ( ( F[i](b)*b ) - ( F[i](a)*a ) ); i++; } return( ans ); } int main() { /* 定義の部分で計算させたい関数を宣言しちゃいます。  */ double (*func_list[])(double)={f1, g1, 0}; printf("∫( %f, %f ) = %f\n", 5.0, 10.0, sub( func_list, 5, 10 ) ); }

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

いちおうこんな方法もありますが.... 外部変数として double (*f_selected)(double); double (*g_selected)(double); を, 被積分関数として double mul_f_g(double x) { return f_selected(x) * g_selected(x); } を定義する. integral を呼出すときには f_selected = func_f[flag1]; g_selected = func_g[flag2]; ans = integral(mul_f_g, a, b); とする. f_selected, g_selected を外部変数とするあたりが反則っぽいんですけど, とりあえず目的は達成できるような. C の範囲できれいにしようとするなら double integral(double (*f)(double x, void *args), double a, double b, void *args); とするんでしょうか.

yassan_yassan
質問者

お礼

回答ありがとうございます. 確かに外部変数を使えばできそうですね. externを使ったりして,考慮してみます. ちなみに, >double integral(double (*f)(double x, void >*args), double a, double b, void *args); この部分は全く同じようにしています.

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

自分では使っていないのですが, C++ で boost を使うという手はあります. #include <functional> #include <boost/compose.hpp> template <typename T> double integral(T &func, double a, double b); とでもしておいて (実装は現在と全く同じ), 実際に使うときには ans = integral( boost::compose_fx_gx( std::multiplies<double>(), std::ptr_fun(func_f[flag1]), std::ptr_fun(func_g[flag2])), a, b); でよかったかと思います. integral の第1引数がとても長いですが, これで x を与えたときに func_f[flag1](x) * func_g[flag2](x) の値を返す関数オ ブジェクトが作成されます.

yassan_yassan
質問者

お礼

回答ありがとうございます. boostは初めて聞きました.初心者ですいません… 少しboostについて見てみたのですが,なかなか難しそうですね. 頑張って勉強していきます.

関連するQ&A

専門家に質問してみよう