指数方程式の解を求める方法と注意点

このQ&Aのポイント
  • 反復計算を使用して、指数方程式の解を求める方法について詳しく説明します。
  • 指数方程式を変形して反復計算を行う方法を紹介します。
  • ニュートン法では負のべき乗や負の指数を計算できないため、別の方法を使う必要があります。
回答を見る
  • ベストアンサー

反復計算で指数方程式の解を求めたい

よろしくお願いいたします。以下方程式(単調増加関数)のxについて求めたいです。 a x + (b x)^1/(n+1) +(c x)^1/(m+1) - d=0 a, b, c, d (定数)を各列に代入、各行の右側にxを求める式を代入し計算するシートを作りたいです。反復計算、循環参照を使用しa,b,c,dの列の横に数式をコピペして一括て求めたいです。 近似解でも良いです。 ためしに式を変形し x={(b x)^1/(n+1) +(c x)^1/(m+1) - d}/a として、たとえば a,b,c,dがA1, B1, C1, D1に代入されており E1:=((B1*F1)^1/(n+1)+(C1*F1)^1/(m+1) -D1)/A1 F1:=E1 として循環参照をさせ、反復回数100、精度0.0001に設定し計算したところ どちらのセルも計算されず、#NUM となってしまいました。 (d=0のときのみx=0と計算できました。) a~d及び指数のn,mの数値の範囲は以下です。 a:0.04-0.07 b:90-100 c:70-90 d:0-100 n::0.157 m:0.352 ニュートン法を用いると負のべき乗または負の指数を計算することになって#NUMとなってうまくいきません。この問題をどうにか回避して計算する方法をご存知の方、ご教示いただきたくお願いします。

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

  • ベストアンサー
  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.6

>a,b,c,dの各条件が1000行程あり、各条件毎にxを算出するには、 No.5で書いたH1,I1,G2を縦ではなく横に並べればいい。 3つ並べるのが面倒なら、1つの式にまとめてください。 A~Fにa,b,c,d,n,m Gにxの初期値 H1に、=G1-($A1*G1+($B1*G1)^(1/($E1+1))+($C1*G1)^(1/($F1+1))-$D1)/($A1+$B1/($E1+1)*($B1*G1)^(1/($E1+1)-1)+$C1/($F1+1)*($C1*G1)^(1/($F1+1)-1)) I,J,K,L,M,N,・・・・にHをコピー 10回くらいもやれば収束するでしょう。

mathstudy
質問者

お礼

早速のご回答ありがとうございます。 ばっちり計算できました。 大変助かりました。 ありがとうございました。

その他の回答 (5)

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.5

ニュートン法です。 (a) A1:0.06294 (b) B1:92.674 (c) C1:80.531 (d) D1:0.45 (n) E1:0.157 (m) F1:0.352 (x0) G1:0.0001 (初期値) (f) H1:=A1*G1+(B1*G1)^(1/(E1+1))+(C1*G1)^(1/(F1+1))-D1 (f') I1:=A1+B1/(E1+1)*(B1*G1)^(1/(E1+1)-1)+C1/(F1+1)*(C1*G1)^(1/(F1+1)-1) (x1) G2:=G1-H1/I1 他のセルは、上のセルをコピー。 これで6回目ぐらいで、x=0.001787631 に収束します。 この関数は上に凸の増加関数なので、初期値の取り方に注意する必要があります。 大きい値を初期値にするとxがマイナスになってしまいます。 できるだけ0に近い正値を初期値にしたほうがいいでしょう。

mathstudy
質問者

お礼

ご回答頂きありがとうございます。 ご指摘の通り、初期値の取り方次第で変わってくることを理解できました。 ありがとうございます。 a,b,c,dの各条件が1000行程あり、各条件毎にxを算出するには、どうしたらよいかご存じありませんでしょうか。 (1000回同じことをすればよいのでしょうが、、、、。) ご教示いただければ幸いです。

  • spring135
  • ベストアンサー率44% (1487/3332)
回答No.4

#3です。 プログラムにミスがあって結果がおかしくなっていました。微分係数に不安定があるようで収束が悪いですが、とりあえず1000回繰り返したところ収束値だけは出ました。 x=0.285632676376962

mathstudy
質問者

お礼

ありがとうございます。 できれば、各a,b,c,dのシートに対しxを一括計算させるようにしたいです。 計算数が多く(1000行くらいあり、また多くのシートを処理しなければなりません。) a,b,c,dが各列に入力されているシートに各行ごとにxを計算するにはどうしたらよいか、 ご存じであればご教示ください。

  • spring135
  • ベストアンサー率44% (1487/3332)
回答No.3

まずはy=a x + (b x)^1/(n+1) +(c x)^1/(m+1) - dのグラフを書いてみてください。 そしたら一目瞭然です。 yを微分してy'を求め ニュートン-ラフソンで x(n)=x(n-1)-y/y' で簡単に求めることができます。 y=a x + (b x)^1/(n+1) +(c x)^1/(m+1) - dがほとんど直線状なので一発で収束します。 多分(b x)^1/(n+1) +(c x)^1/(m+1)は効いてこないのでしょう。 a:0.05 b:95 c:80 d:50 n::0.157 m:0.352 のとき x=-0.315623356 >ためしに式を変形し x={(b x)^1/(n+1) +(c x)^1/(m+1) - d}/a 何のための変形ですか。

mathstudy
質問者

お礼

ご回答をありがとうございます。 おっしゃる通り確かにグラフを描くと一目瞭然なのですが、 なぜか収束できません。 x={(b x)^1/(n+1) +(c x)^1/(m+1) - d}/a の変形は、循環参照させてセル同士を参照させると同じ値に収束して求めることができた経験からです。 エクセルの循環参照と反復計算のヘルプを見て可能と思い実施してみたところうまく収束しました。 その時は、指数が整数のためか収束し解を得ることができました。 今回は、ニュートン法の途中でべき乗の中身が負となる場合がありエクセルが計算できず #NUMを返したとようです。 (負のべきはエクセルでサポートされていないようです。)

noname#221368
noname#221368
回答No.2

>ニュートン法を用いると・・・ と書かれているので、ゴールシークだけでなく、マクロ(VBA)もやった事があると思って良いですか?。以下は、VBAを使えるが前提です。  単調増加になるa,b,c,d,n,mを与える訳ですから、解はあったとして1個です。2分法(bysection)はどうでしょう?。解が0以上にあるなら、計算過程で負数のべき乗や負数の指数を計算する事はありません。  2分法はニュートン方に比べて遅いと言われていますが、最近のPCは信じられないくらい速いので、この程度なら恐らく、体感速度は0ですよ。それにアルゴリズムは簡単だし(与式を単に計算するだけ(^^))、解精度の制御もしやすいし・・・(^^)。

mathstudy
質問者

お礼

ご回答頂きありがとうございます。 おっしゃるとおり、単調増加ですので試算すると解は1個なのですが、質問の結果となってしまいました。 2分法については、知見がないのです。ご教示いただければ幸いです。 当方PC環境はWIN7でOFFICE2010です。 VBA等で関数を定義できて、引数に方程式とxを入れて、解くマクロとかあると助かります。 ご存じであれば、自分はVBAの知識はほとんどないのですが、ご教示いただけると助かります。

mathstudy
質問者

補足

申し訳ありません。 2分法を良く知らず、勝手なコメントをしてしまいました。 (引数に関数と、xを入れてxの値を返すVBAなるものをお尋ねしてしまいました。) 2分法の計算方法とVBAをネットで探してみましたが、なかなか奥深く見つけるのが大変でした。 勝手なコメントをして申し訳ありません。 もし、お気を悪くされず、質問の対策方法を引き続きご教示いただければ幸いです。

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.1

a x + (b x)^(1/(n+1)) +(c x)^(1/(m+1)) - d = 0 でしょうか。 >ニュートン法を用いると負のべき乗または負の指数を計算することになって xが負になるのならだめですが、指数は負でも計算できます。 ニュートン法で問題なく計算できますよ。 a,b,c,dがどんな値のとき#NUMになったんでしょうか。

mathstudy
質問者

お礼

早速のご回答ありがとうございます。 ニュートン法でためしにx_k=x_k-1-f(x)/f'(x)で計算しましたが、初期値を1にしたらいきなり、 xが負で帰ってきてしまいました。以降f'(x)が#NUMとなって以降の計算ができませんでした。 値は質問の範囲で求めたいですが、ためしに以下条件で行いました。 a:0.06294 b:92.674 c:80.531 d:0.45 n::0.157 m:0.352

関連するQ&A

  • 4次方程式の解

    この度はよろしくお願いいたします。 題名のとおりで 次のサイト様 ttp://www.akamon-kai.co.jp/yomimono/kai/kai.html の計算方法(フェラーリの公式)を用いて4次方程式を 代数的に解こうとしたのですが初めてプログラムをしたに等しいので うまく解が出てきてくれません。 見にくいとは思いますがプログラムを以下に示しますので どこを直せばよいかの修正方法・もしくは他の方法がありましたらどうかよろしくお願いします。 use Math::Complex; # 定数の入力 print "aの値は?\n"; $a = <STDIN>; print "bの値は?\n"; $b = <STDIN>; print "cの値は?\n"; $c = <STDIN>; print "dの値は?\n"; $d = <STDIN>; print "eの値は?\n"; $e = <STDIN>; # ω・p1~p3の式 $j = (-1 + sqrt(-3))/2; $k = (-1 - sqrt(-3))/2; $f = -8*$a*$c+3*$b*$b; $g = -72*$a*$c*$e+27*$a*$d*$d+27*$b*$b*$e-9*$b*$c*$d+2*$c*$c*$c; $o = -256*$a*$a*$a*$e*$e*$e+192*$a*$a*$b*$d*$e*$e+128*$a*$a*$c*$c*$e*$e-144*$a*$a*$c*$d*$d*$e; $p = 27*$a*$a*$d*$d*$d*$d-144*$a*$b*$b*$c*$e*$e+6*$a*$b*$b*$d*$d*$e+80*$a*$b*$c*$c*$d*$e; $q = -18*$a*$b*$c*$d*$d*$d-16*$a*$c*$c*$c*$c*$e+4*$a*$c*$c*$c*$d*$d+27*$b*$b*$b*$b*$e*$e; $r = -18*$b*$b*$b*$c*$d*$e+4*$b*$b*$b*$d*$d*$d+4*$b*$b*$c*$c*$c*$e-$b*$b*$c*$c*$d*$d; $h = $o + $p + $q + $r; # xの3乗根を指数対数で表した式 $s = exp(log($g+3*sqrt(3*$h)/3)); $t = exp(log($g-3*sqrt(3*$h)/3)); # 解 $x1 = 1/(12*$a)*(-3*$b+sqrt(3*($f+2*$a*($s+$t)))+sqrt(3*($f+2*$a*($j*$s+$k*$t)))+sqrt(3*($f+2*$a*($k*$s+$j*$t)))); $x2 = 1/(12*$a)*(-3*$b+sqrt(3*($f+2*$a*($s+$t)))-sqrt(3*($f+2*$a*($j*$s+$k*$t)))-sqrt(3*($f+2*$a*($k*$s+$j*$t)))); $x3 = 1/(12*$a)*(-3*$b-sqrt(3*($f+2*$a*($s+$t)))+sqrt(3*($f+2*$a*($j*$s+$k*$t)))-sqrt(3*($f+2*$a*($k*$s+$j*$t)))); $x4 = 1/(12*$a)*(-3*$b-sqrt(3*($f+2*$a*($s+$t)))-sqrt(3*($f+2*$a*($j*$s+$k*$t)))+sqrt(3*($f+2*$a*($k*$s+$j*$t)))); # 解が成立する時の条件 if($s*$t == 4*(12*$a*$e-3*$b*$d+$c*$c) , sqrt(3*($f+2*$a*($s+$t)))*sqrt(3*($f+2*$a*($j*$s+$k*$t)))*sqrt(3*($f+2*$a*($k*$s+$j*$t))) == 27*(-8*$a*$a*$d+4*$a*$b*$c-$b*$b*$b )){ print $x1 , "\n"; print $x2 , "\n"; print $x3 , "\n"; print $x4 , "\n"; } else{break;}

  • 2次方程式の解

    ax^2+bx+c=0の方程式について abcを自分で入力して、「2次方程式として成り立つか」の判断をし、2次方程式であればその解を求めるプログラムです。 2次方程式の解き方をなんとなく忘れていたので、数IIの教科書やらで確認してみました。 以下のように作成したのですが、解が出るはずの値を入力しても強制的に終了してしまいます。どこがおかしいのでしょうか? 他に気になる点は、メイン関数にて「2次方程式として成り立った場合」にはサブへ移動ができているのでしょうか。 あと、仮に↑が合っていたとして、異なる2つの虚数解の計算方法は以下のやり方でも良いのかどうかもお聞きしたいです。 よろしくお願いします。 #include<stdio.h> #include<math.h> void niji(double a,double b,double c){ double x1,x2,x3,y1,y2,D; D=b*b-(4.0)*a*c; if(D>0){ printf("2つの異なる実数解\n"); x1=(-b+sqrt(D))/(2.0*a); x2=(-b-sqrt(D))/(2.0*a); printf("x= %f , %f \n",x1,x2); } else if(D==0){ printf("重解\n"); x3=(-b)/(2.0*a); printf("x= %f \n",x3); } else{ printf("2つの異なる虚数解\n"); x3=(-b)/(2.0*a); y1=sqrt(D)/(2.0*a); y2=-sqrt(D)/(2.0*a); printf("x= %f + i %f, %f - i %f\n",x3,y1,x3,y2); } return; } int main(void){ double a,b,c; printf("ax^2+bx+c=0の式のabcを入力せよ\n"); while(scanf("%f %f %f",&a,&b,&c)){ if(a==b==c==0){ break; } else if((a==b==0)&&(c!=0)){ printf("不能\n"); } else if((a==0)&&(b!=0)){ printf("1次方程式になる\n"); } else{// 入力されたabcが↑の3つに該当しなければ niji(a,b,c);//←サブ関数に示した2次方程式を解く } } return 0; }

  • 2次方程式の解 Cプログラミング

    C言語でのプログラムの添削をお願いします。 2次方程式の解を求めるものなのですが。 #include<stdio.h> #include<math.h> main(){ double a,b,c,d; double x1=0; double x2=0; scanf("%lf %lf %lf" ,&a,&b,&c); printf("a=%f b=%f c=%f\n" ,a,b,c); d=b*b-4*a*c; if(d>0){ x1=(-b+sqrt(d))/2*a; x2=(-b-sqrt(d))/2*a; printf("x=%f,%f\n" ,x1,x2); }else if(d<0){ x1=-b/2*a; x2=sqrt(-d)/2*a; printf("x=%f+%fi,%f-%fi\n" ,x1,x2,x1,x2); }else{ printf("x=%f\n" ,x1); } return 0; } このとき、 a=-7,b=2,c=-1 を与えると x=7.000000+-17.146428i,7.000000--17.146428i という値が返ってきます。 他にも、虚数解のときに間違った値が返ってきてしまう気がするのですが、いかがでしょうか? 実数解のときは正しいようです。 回答よろしくお願いします。

  • 3次方程式の1つの解から他の解を導く公式

    有理係数の整式 f(x)=x^3+ax^2+bx+c は有理数の範囲で因数分解できなく, d=√(a^2b^2-4a^3c+18abc-4b^3-27c^2)     が有理数であるとする. このとき,方程式 f(x)=0 の1つの解をθとするとき,他の解をθの最低次の整式として表せ. (答)(-1/2)(θ+a)±(1/2d){2(-a^2+3b)θ^2+(-2a^3+7ab-9c)θ-a^2b-3ac+4b^2} dはどこから出てきたのかも含めて、最低次の整式が答えのようになる計算ががまったくわかりません。

  • 4次方程式の解についての問題

    f(x)=x^4-kx^2+4x+k+3で、f(x)=0が異なる4つの実数解をもち、4つの解a,b,c,dをa<b<c<dとする。 a+c+dとacdをそれぞれkを用いて表せ。(慶応理工 今年) f(x)=(x+1){x^3-x^2+(1-k)x+k+3}だから、1つの解は-1とわかる。 f(x)=0から、k=x^2+1-{4/(x+1)}となり、g(x)=x^2+1-{4/(x+1)}のグラフから、c=-1。 x^3-x^2+(1-k)x+k+3=0の解が、a,b,dとなり解と係数から、 a+b+d=1・・(1) ab+bd+da=1-k・・・(2) abd=-k-3・・・(3) (1)(2)(3)からa+dとadをkの式で表せればよいと思いましたが、できませんでした。 アドバイスをよろしくお願いします。 因みにこのあとに続きの問いがあって、k->∞のとき、bcの値の極限値を求めよ、これは グラフから考えて、b->-1 だから、1になりました。

  • 一次方程式の解を教えて下さい。

    x={a(b-c-d-e)-[1.25ef+1.25f(x+g)]-[0.25eh+0.25h(x+g)]-[1.35ei+1.35i(x+g)]}÷[(a+1.25f)+0.25h+1.35i] xの値を教えて下さい。 よろしくお願いいたします。

  • 行列の指数関数について

    行列の指数関数について 「exp(X)=E+Σ(1/n!)X^nとした時に、exp(tA)を求めよ」という問題で、(3×3)行列 (tA)^n=t^n  (2・2^n-3^n   -2^n+3^n  -2^n+3^n)  (1-3^n      3^n     -1+3^n)  (-1+2・2^n-3^n -2^n+3^n  1-2^n+3^n) となって、2^n,3^nをeにした後に上の行列に代入すると、自分で計算した値と答えの値が違くなってしまいます。(a13,a32,a33のところ) なのでeについて求めた後に、代入したときの計算教えてください。 見づらくて、すいませんm(--)m

  • 指数方程式の問題です

    指数方程式の問題です。 27*2^y/3^3x=3^2y/2^(2x-1) 答えの所に 変形して 3^3*3^-3x*2^y=3^2y*2^-(2x-1) とあるのですが、左辺については、わかっていると思うのですが右辺がわかりません。 左辺は底をそろえて 3^3/3^3x*2^yと考えれば、指数法則の a^m/a^n=a^(m-n)を使えばできますよね。 でも右辺は、分母と分子の底が2・3と違うのでこの指数法則は使えませんよね? この右辺はどのような考え方で変形しているのでしょうか? 自分がこの指数法則の定義、その他を勘違いしているのでしょうか? 宜しくお願いいたします。

  • 指数方程式の解

    xについての以下の方程式が正の解と負の解をそれぞれ1つずつもつとき、 定数aの範囲を求めよ。 【自分の解答】 2^x =tとおく。 (t>0) (与式)=t^2 -(a^2)t+2a^2 +4a-6=0 2つの解をα、βとすると、解と係数の関係より、 αβ=2a^2 +4a-6=0 [1]αβ<0であればよい。 a^2 +2a-3<0 (a+3)(a-1)<0 -3<a<1 [2]判別式D>0であればよい。 D=a^4 -8a^2-16a+24>0 ここで手詰まりです(>_<) 詳しい解説と解答お願いします。

  • 2次方程式の解

    今回、大学の授業で課題が出たのですが、どうしても問題文に書かれている条件を満たせず再提出になってしまいました。 もし、分かる方がいらっしゃいましたら、お力をお貸しいただけないでしょうか。お願いします。 問題  ax^2+bx+c=0の式においてa,b,c(double型)をmainの中でキーボードから入力して、2次方程式の解を求める関数を作りmainの中で根を表示するプログラムを作りなさい。(判別式が負になる場合は共役な複素数根になる。) main→関数  a,b,cの係数 関数→main  方程式の根(2個)[複素数の構造体にする] 私は以下のプログラムを提出しましたが、「複素数の構造体を用いて、構造体のポインタを使ったプログラムにしてください」 #include<stdio.h> #include<math.h> typedef struct{ double a,b,c,ha,an1,an2,re,im; }COMP; void main() { COMP s; COMP x(COMP); printf("aを入力してください===>"); scanf("%lf",&s.a); printf("bを入力してください===>"); scanf("%lf",&s.b); printf("cを入力してください===>"); scanf("%lf",&s.c); s=x(s); if(s.ha>=0) { printf("xは %.2lf,%.2lfです\n",s.an1,s.an2); } else if(s.ha<0) { printf("xは %.2lf + %.2lfi,%.2lf - %.2lfiです\n",s.re,s.im,s.re,s.im); } } COMP x(COMP p) { COMP d; d.ha=p.b*p.b-4.0*p.a*p.c; if(d.ha>=0) { d.an1=(-p.b+sqrt(d.ha))/(2.0*p.a); d.an2=(-p.b-sqrt(d.ha))/(2.0*p.a); } else if(d.ha<0) { d.re=-p.b/(2.0*p.a); d.im=sqrt(-1.0*d.ha)/(2.0*p.a); } return d; }