C言語プログラム(二分法)についての質問

このQ&Aのポイント
  • C言語プログラム(二分法)でa*xの最大点を求めるためのプログラムは?
  • C言語プログラム(二分法)でaを1〜10まで変化させたときのxの値を求めるためのループはどうすればいいか?
  • C言語プログラム(二分法)による解の求め方について質問です。
回答を見る
  • ベストアンサー

C言語プログラム(二分法)について質問です。

C言語プログラム(二分法)について質問です。 以下作成したプログラムでは、aを入力すると, x=b - (log(a)) - (a+x)/2の解が求まります。(今回式は適当ですが。) 二分法で解を求めるというプログラムは作成できたのですが、 このプログラムで、aを1~10まで変化させたときのxの値というようなループをプログラムでしたうえで、 a*xの値がもっとも大い点を求めるためにはどのようなプログラムを組めば(これを改良すれば)いいのでしょうか? 具体的に行いたいことは、この二分法のプログラムをaとxの関数とし、a*xの最大点を求めたいのです。 質問が分かりにくいかもしれませんが、お願いします。 以下作成したプログラムです。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define eps 1.0e-6 double b=0.3; double a=0; double f(double x); void nibun(void); int main() { nibun(); return 0; } void nibun(void) { int count; double x0,x1,m; printf("aの値\n"); scanf("%lf",&a); count=0; x0=-2*b; x1=b; do { count++; m=(x0+x1)/2.0; if(f(m)*f(x0)<0) x1=m; else x0=m; if(count==700) { printf("Error\n"); exit(1); } } while (!(fabs(x0-x1)<eps)); printf("解の値は %f\n",m); } double f(double x) { return(b - (log(a)) - (a+x)/2); }

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

  • ベストアンサー
回答No.3

関数 nibun() は、係数入力の printf(); scanf(); を省いただけで、そのまま用いています。 プログラムは計算区間を #define で START,END,STEP定数化したり、式を事前に定義(formula())し、変更はプログラム本体を触らなくても良いようにしてあります。 なお、変数a は実数であるため、よくある for()の桁落ち誤差が発生しても大丈夫なように1%(STEP/100.0)の重みを付けてあります。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define EPS 1.0e-6 #define START 1.0 // aの始点 #define END 10.0 // 〃終点 #define STEP 1.0 // 〃刻み #define formula(a,x) a*x // 検討式 double f(double); double nibun(void); double a,b=0.3; // 広域変数 int main(void) { double x, max, max_a, max_x; for (a=START; a<=END+STEP/100.0; a+=STEP) { x=nibun(); if (a==START || formula(a,x)>max) { max_a=a; max_x=x; max=formula(a,x); } } printf("max(a*x)= %.1F * %f = %f\n", max_a, max_x, max); return 0; } double nibun(void) { int count=0; double x0,x1,m; x0=-2*b; x1=b; do { count++; m=(x0+x1)/2.0; if(f(m)*f(x0)<0) x1=m; else x0=m; if(count>=700) printf("Error\n"), exit(1); } while (!(fabs(x0-x1)<EPS)); printf("\t解の値は a=%.1f のとき %f\n",a,m); return m; } double f(double x) { return b - log(a) - (a+x)/2; }

その他の回答 (2)

回答No.2

main() をこんな感じに書き直します。 (ただし、この main() は、No.1 の方の回答とほぼ同じロジックを書き直しただけです) 当然、このままでは nibun() の呼び出しに失敗しますから、 「方程式の解を表示する関数」void nibun(void) を、 「定数 a を指定したら、方程式の解 x を返す関数」double nibun(double a) となるように書き直します。 オリジナルの nibun() の中でわざわざ「a を入力」したり、「結果を表示したり」していますから、引数の a をどう処理するとか、結果はどこに求まっているかはわかると思います。 double nibun(double a); int main() { int resultA = -1; double resultX = 0; for(int a = 0; a <= 10; a++) { double x = nibun(a); if ((resultA < 0) || (rsultX < a * x)) { resultA = a; resultX = a * x; } } // ここで、resultA と resutlX に答えが求まる } あと、nibun() の引数として a を持つことから、 double f(double x) を double f(double a, double x) に変更して、呼び出し時に a を私のも良いかもしれません。

  • patawan
  • ベストアンサー率16% (2/12)
回答No.1

プログラムの細かい部分はお任せします。 ココでは質問内容にあった『aの値を変化させ、最大値を求める』という点に絞って説明します。 aを1から10まで変化させる為にループ文を使います。 for (i=0 ; i < 10 ; i++) { } こんな感じですね。 このfor文の{}内でaの値は変化しますので、その中でxの値を求め、a*xの値(xx)を求めます。 for (i=0 ; i < 10 ; i++) { x = ・・・(xの計算式) ; xx = a * x ; } max_xの値(前回までの最大値)とxの値を比較し、xxの方が大きければmax_xにxxの値を入れます。(max_xの値の方が大きければ、スル~) for (i=0 ; i < 10 ; i++) { x = ・・・(xの計算式) xx = a * x ; if ( max_x < xx ) { max_x = xx ; } } って、こんな感じじゃダメかな? 変数の初期化は必ず行って下さいね。

qwe1232
質問者

補足

回答ありがとうございます。 今回の式は x=~ という形では解が求まらないため、二分法を用いて解析的にといています。 回答にあるような感じのことならばできるのですが、二分法を用いたプログラムは記載したように、 関数が二つに分かれています。 そのため、回答のように、for文を作ってただ式を入れて解を比較する。ということができません。 このような場合において、aの値を変化させ、最大値を求める。ということをしたい場合、 記載したプログラム(二分法)のどの部分に何を書き加えればよいのかということを教えていただきたいです。

関連するQ&A

  • C言語 二分法

    初投稿です。 お恥ずかしながらパソコンが苦手で、Cゲッが難しくてできません。 今回二分法です。 途中まではやったのですができません。 演習 0~1の乱数を12個発生させ,これらの平均をxi,yi とする。(s,tは乱数) xi=1/12(x1i+x2i+....x12i) yi=1/12(y1i+y2i+....y12i) このようなを1000個作り,(xi,yi)で散布図 を作りなさい。またx,yのそれぞれの平均を求 めよ。 この演習で #include<stdio.h> #include<stdlib.h> #include<math.h> #define eps 1.0e-5 float f(double x); void nibuin(void); int main () { int count; double a,b,m; count=0; printf("範囲の左の値を入力してください。\n"); scanf("%lf",&a); printf("範囲の右の値を入力してください。\n"); scanf("%lf",&a); if(count==1000){ printf("収束しませんでした。\n"); exit(1); } } while(!(fabs(a-b)<eps)); printf("解の値は%f\n収束するのに%d回かかりました。"m,count); } float f(double x) { reurn x*sin(x)+log(x); } まではできたのですが、 scanf("%lf",&a);とif(count==1000){の間に入る命令が打てません。 よろしくお願いします。

  • C++でのプログラムについての質問です

    このような二次関数の解を求めるプログラムを作成したのですが、自作関数solveをvoid solve(double, double, double)のように変更し同じ動作をするように変更したいです どのようにへんこうすればよいでしょうか #include<stdio.h> #include<stdlib.h> #include<math.h> int main(void) { double a, b, c; /*二次方程式の定数*/ double D, x1, x2, r1, r2; printf("ax^2 + bx + c = 0 の係数 a, b, c を入力してください---> \n"); scanf_s("%lf %lf %lf", &a, &b, &c); printf("2次方程式を解いた結果は次の通りとなる。\n"); if (a == 0.0) { if (b == 0.0) { printf("係数がおかしい\n"); exit(-1); } { x1 = -c / b; printf("解は%f です。\n", x1); exit(0); } } else { D = b * b - 4 * a * c; if (D >= 0) { x1 = (-b + sqrt(D)) / (2.0 * a); x2 = (-b - sqrt(D)) / (2.0 * a); if (D == 0.0) { printf("解は %f です。\n", x1); } else { printf("解は %f と %f です。¥n", x1, x2); } } else { r1 = -b / (2 * a); r2 = sqrt(-D) / (2 * a); printf("解は%.2f+%.2fi と%.2f-%.2fi \n", r1, r2, r1, r2); } } return 0; }

  • ニュートン法をC言語でプログラム

    方程式 cos^2x-0.5=0 (0<x<π) の解をニュートン法で求める という問題をC言語のプログラムを作り計算したいのですが分かりません。 自分で考えてみたプログラムは以下の通りです。 #include <stdio.h> #include <math.h> #define f1(x) cos(x)*cos(x)-0.5 #define f2(x) sin(2*x) /* ニュートン法による方程式の解 */ main() { double x0,x1,a,b,c,d,g,n; a=1; x0=0.7; n=0; while(a>0.0001){ b=x0; d=f1(b); g=f2(b); x1=x0-d/g; c=x1; a=f1(c); n=n+1; printf(" n= %f x1=%f x0=%f\n",n,x1,x0); printf(" a= %f → 解 x= %f \n", a,x1); x0=x1; } } 自分としてはこれが精一杯で、何故間違ってるのか、何をどうすればいいのか、さっぱり分かりません。どういったところが間違ってるのか可能性だけでも示して頂ければ幸いです。 参考として、ニュートン法によるプログラム例として書かれていたものを上げさせて頂きます。 例: e^x-3=0 の解をニュートン法により計算する。 #include <stdio.h> #include <math.h> #define f1(x) exp(x)-3 #define f2(x) exp(x) /* ニュートン法による方程式の解 */ main() { double x0,x1,e,a,b,c,d,g,n; a=1; x0=3; n=0; while(a>0.0001){ b=x0; d=f1(b); g=f2(b); x1=x0-d/g; c=x1; a=f1(c); n=n+1; printf(" n= %f x1=%f x0=%f\n",n,x1,x0); printf(" a= %f → 解  x= %f \n", a,x1); x0=x1; } }

  • 二分法のプログラムについて

    下の用なプログラムを作ったのですがどうしても正しい答えを導くことができません。自分でもいろいろ調べてみましたがわかりません。誰かご教授宜しくお願いします。 #include<stdio.h> #include<stdlib.h> #define MAX 10 int n , count; double c[MAX+1]; double a,b,e; void nyuuryoku(void) { int i; printf("nの入力>"); scanf("%d",&n); if(n>MAX){printf("最大次数を超えている");exit(1);} else if(n<0){printf("nが負");exit(2);} else{for(i=0;i<=n;i++){printf("係数の値>");scanf("%lf",&c[i]);} }} double f(double x) {double y; int i; y = c[0]; for(i=1;i<=n;i++){ y=y*x+c[i];} return y; } void hani(void){ printf("aの値>");scanf("%lf",&a); printf("bの値>");scanf("%lf",&b); printf("eの値>");scanf("%lf",&e); if(e<=0){printf("eが0または負"); exit(3);} if(f(a)==0){printf("%f",f(a)); exit(4);} if(f(b)==0){printf("%f",f(b)); exit(5);} if(f(a)*f(b)>0){printf("初期値異常"); exit(6);}} double nibun(void) {double c; if(b>a){ while(b-a>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(a)*f(c)<0){b=c;} if(f(b)*f(c)<0){a=c;} } return a;} if(a>b){ while(a-b>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(b)*f(c)<0){a=c;} if(f(a)*f(c)<0){b=c;} } return a;} } void syutsuryoku(double x){ printf("x=%lf\n",x); printf("f(x)=%lf\n",f(x)); printf("繰り返し回数=%d\n",count); } int main(void){ double ans; count=0; nyuuryoku(); hani(); ans = nibun(); syutsuryoku(ans); }

  • C言語についての質問です

    プログラミング初心者です if関数を使用して二次方程式の解を解くプログムを作成したのですが、この作成した関数をユーザー定義関数を使用しmain 関数の中でユーザー定義関数を呼び出すことにより、 2次方程式の解を求めるプログラムへ変更したいのですが、どのように行えばいいのか分かりません… 私が作成したプログラムはこのようなものになっています #include<stdio.h> #include<stdlib.h> #include<math.h> int main(void) { double a, b, c; /*二次方程式の定数*/ double D, x1, x2, r1, r2; printf("ax^2 + bx + c = 0 の係数 a, b, c を入力してください---> \n"); scanf_s("%lf %lf %lf", &a, &b, &c); printf("2次方程式を解いた結果は次の通りとなる。\n"); if (a == 0.0) { if (b == 0.0) { printf("係数がおかしい\n"); exit(-1); } { x1 = -c / b; printf("解は%f です。\n", x1); exit(0); } } else { D = b * b - 4 * a * c; if (D >= 0) { x1 = (-b + sqrt(D)) / (2.0 * a); x2 = (-b - sqrt(D)) / (2.0 * a); if (D == 0.0) { printf("解は %f です。\n", x1); } else { printf("解は %f と %f です。¥n", x1, x2); } } else { r1 = -b / (2 * a); r2 = sqrt(-D) / (2 * a); printf("解は%.2f+%.2fi と%.2f-%.2fi \n", r1, r2, r1, r2); } } return 0; } よろしくお願いいたします

  • C言語課題(数値計算)お願いします。

    課題内容 ニュートン法を用いて√2の値を求められるプログラムを作る。 10ケタまで表示する。 書いてみたソースコード #include <stdio.h> #include <stdlib.h> #include <math.h> #define max 1000 //最大繰り返し回数 #define eps 1.0e-10 //収束条件 double f(double x); double df(double x); void newton(void); int main() { newton(); return 0; } void newton(void) { int count; double a,newa; count=0; printf("初期値を入力してください。\n"); scanf("%lf",&a); for(;;) { count++; newa=a-f(a)/df(a); if(fabs(newa-a)<eps) break; a=newa; if(count==max) { printf("収束しませんでした。\n"); exit(1); } } printf("解の値は %f\n収束するのに %d 回かかりました。\n", newa,count); } double f(double x) { return x*x-2; } double df(double x) { return 2x; } コンパイルできません。 間違いとどうすればよいかを教えていただけるとありがたいです!!!

  • c言語 プログラミング(初心者)

    解を判定するプログラミングを作成したのですが、a,b,cを0,1,2と入力したときに解に0.00000が出てきて解がおかしくなります。 どなたか詳しい方教えてください。また簡潔にできる点などありましたらご指摘お願いします。 #include <stdio.h> #include <math.h> int main (void) { double a,b,c,d,x1,x2; printf("ax^2+bx+c=0 の係数を入力してください\n"); scanf("%lf %lf %lf",&a,&b,&c ); if(a==0){ if(b==0) { printf("解は存在しません\n"); } else { x1=-c/b; printf("解は %f です\n",x1); } } else { d=b*b-4*a*c; if(d>=0){ x1=(-b+sqrt(d))/(2.0*a); x2=(-b-sqrt(d))/(2.0*a); if(d==0){ printf("解は %f (重解)です\n",x1); } else { printf("解は %f と %f です\n",x1,x2); } } else { printf("実数解は存在しません(虚数解)\n"); } } return 0; }

  • C++でのプログラミングについてです

    プログラミング初心者です C++で二次方程式の解のプログラムを作成したのですがうまく作動させることができません…どこがおかしいのでしょうか、またどのように変更すればよいでしょうか 発生したエラーは 15行 型voidの値をintのエンティティに割り当てることはできません 34行 宣言が必要です 55行 宣言が必要です 15行 voidが他の型と同時に使われました 34行 '{'を見つけました(関数のヘッダーがないかもしれません). 68行 構文エラー:'}' です よろしくお願いいたします #include<stdlib.h> #include<math.h> void solve(double, double, double); int main(void) { double a, b, c; /*二次方程式の定数*/ double D, x1, x2, r1, r2; int ret; printf("ax^2 + bx + c = 0 の係数 a, b, c を入力してください---> \n"); scanf_s("%lf %lf %lf", &a, &b, &c); printf("2次方程式を解いた結果は次の通りです。\n"); ret = solve(a, b, c, &x1, &x2, &r1, &r2); switch (ret) { case-1: printf("係数がおかしい\n"); break; case 0: printf("解は虚数解で%.2f+%.2fi と%.2f-%.2fi です\n", r1, r2, r1, r2); break; case 1: printf("解は実数解となり、%f です。\n", x1); break; case 2: printf("解は実解解で、%f と %f です。¥n", x1, x2); break; } return 0; } void solve(double a, double b, double c, double x1, double x2, double r1, double r2); { if (a == 0.0) { if (b == 0.0) { return -1; } { x1 = -c / b; return 1; } } else { D = b * b - 4 * a * c; if (D >= 0) { x1 = (-b + sqrt(D)) / (2.0 * a); x2 = (-b - sqrt(D)) / (2.0 * a); return 1; } if (D == 0) { x1 = -b / (2 * a); return 1; } else { r1 = -b / (2 * a); r2 = sqrt(-D) / (2 * a); return 0; } } }

  • c言語です。

    c言語です。 実行結果 式 3 X1 + 2 X2 + 1 X3 = &g 2 X1 + 5 X2 + 2 X3 = &g 1 X1 + 4 X2 + 1 X3 = &g 解 X1 = 1 X2 = 2 X3 = 3 を 式 3 X1 + 2 X2 + 1 X3 = 10 2 X1 + 5 X2 + 2 X3 = 18 1 X1 + 4 X2 + 1 X3 = 12 解 X1 = 1 X2 = 2 X3 = 3 に直したいのですが&gの所をどのようにしたら10.18.12になりますか? #include <stdio.h> #include <float.h> #define N 3 double A[N][N] = {{3,2,1}, {2,5,2}, {1,4,1}}; double b[N] = { 10, 18, 12 }; void Gauss_J( int, double*, double* ); void main(void) { int i; printf( "%d式\n", N ); for( i = 0; i < N ; i++ ) { printf( "%g X1 + %g X2 + %g X3 = &g \n", A[i][0], A[i][1], A[i][2], b[i] ); } printf("解\n"); Gauss_J(N, (double *)A, (double *)b ); printf("X1 = %g \n", b[0]); printf("X2 = %g \n", b[1]); printf("X3 = %g \n", b[2]); } void Gauss_J(int n, double *a, double *b) { int p, i, j,I ; double pivot, c ; for ( p = 0 ; p < n ; p++ ) { pivot = a[ p*n + p ]; for ( i = p ; i < n ; i++ ) { a[ p*n + i ] /= pivot; } b[ p ] /= pivot; for ( I = 0 ; I < n ; I++) { if (I != p) { c = a[ I*n + p]; for ( j = p ; j < n; j++ ) { a[ I*n + j] -= c * a[ p*n + j ]; } b[ I ] -= c * b[ p ]; } } } return ; }

  • はさみうち法のプログラム(C言語)について

    調べたりしながら私なりに書いてみたのですが上手くいきません。 「ans=1.048404」とならなければいけないのに 「nan」で返ってきてしまうのです。 どこをどの様に変えたら良いのでしょうか・・・? ※課題の締め切りが近いので,早急にご回答宜しくお願い致します! 以下、はさみうちのプログラム↓ #include<stdio.h> #include<math.h> /*初期値x0,*/ /*f(x)を定義*/ double f(double x){ return sqrt(x*x+10.0) - 10.0*exp(-x*x); } /*はさみうち法の関数*/ double hasamiuchi(double x0,double x1,double eps,double imax){ double x2; /*x軸との交点*/ int i; /*繰り返しの回数*/ if(f(x0)*f(x1)>0){/*x0とx1が同符号の場合x1をx0とする*/ x0=x1; } for(i=0;i<imax;i++){ x2=(x1*f(x0)-x0*f(x1))/(f(x0)-f(x1)); /*x0とx1で出来る直線とx軸の交点x2を求める*/ x1=x2; /*x2の値を次のループにおけるx1とする*/ } if(fabs(x1-x0)<eps) return x2; /*収束したら解x2を返す*/ return 0.0/0.0; /*収束しなかったらnanを返す*/ } int main(void){ printf("ans = %f\n", hasamiuchi(2.0,1.0,1e-6,20));/*値を代入してはさみうちの実行*/ return 0; }