【先着1,000名様!】1,000円分をプレゼント!

学校で出されたCプログラムの課題で、1問だけどうしても出来ない問題があるんです。
「方程式 f(x) = x2 - 2 = 0 を 2 分法を用いて解くプログラムを作成せよ。ここで、方程式 f(x) = x2 - 2 は関数として定義せよ。上位の方から 4 桁目まで正しい値が出たらループを止めるようにする。」
というものなのですが、この「2分法」というやり方もよく分かりません。
プログラムの作成方法と併せて教えて頂けると幸いです。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

こんな感じでしょうか?



#include <stdio.h>

/* 関数 f(x) */
double f(double x) {
 return x*x-2.0;
}

/* 二分法 初期値 x1<x2 と 誤差限界 eps を入力 */
double bisec(double x1, double x2, double eps) {
 double x;
 while (x2 - x1 >= eps) {
  x = (x1+x2)/2.0; /* 中点計算 */
  if (f(x1)*f(x) > 0.0) { /* 同符号か判定 */
   x1 = x;
  } else {
   x2 = x;
  }
 }
 return (x1+x2)/2.0;
}

int main(void) {
 double eps=0.00001;
 printf("%lf %lf\n",bisec(-2,0,eps), bisec(0,2,eps));

 return 0;
}
    • good
    • 3
この回答へのお礼

実行できました!!!!!本当にありがとうがざいます。
JaritenCatさんには何度も助けて頂いていますね。本当に感謝しています。
感謝の意を込めて良回答にさせて頂きます。ありがとうございました。

お礼日時:2005/01/28 23:42

2分法というのは、ぶっちゃけて言えば、


関数のマイナスになる値とプラスになる値の間のどこかに0になる部分があるということで、その範囲を2分割して狭めていく方法です。(多分^^;)
例えば、
f(1)=-1で
f(2)=2ですから
1と2の間のどこかに、0になるようなXが存在します。
そこで、仮に、(1+2)/2の値
f(1.5)を求めてみると
0.25になります。これは正ですので
f(1)=-1で
f(1.5)=0.25
となって1と1.5の間にあります。
次に(1+1.5)/2の値を求めてみると
f(1.25)=-0.4375
となって今度は負になりましたので、
1.25と1.5の間にあることになります。
まあ、そんな感じで求めます。

参考URL:http://okweb.jp/kotaeru.php3?qid=1143518
    • good
    • 2
この回答へのお礼

早速のご回答ありがとうございました。
何だかプログラムにするのは難しそうですね…
頑張ってみます!!!!!ありがとうございました!!!

お礼日時:2005/01/28 22:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC言語の二分法のプログラムについて

二分法によりルート2の近似値を求めるプログラム、ってどうやって作ったらいいんですか?
ちなみに初期値は2で、収束条件は10^-5です。
収束までの回数も求めなきゃいけません(ニュートン法と比較するため。ちなみにニュートン法はできました。)

似たような質問を見つけたのですが、どれも、難しいプログラムばかりで解読ができません。
関数とかif else文とかwhile文とかfor文とか、そういう簡単なのしか習ってないので、それで作れる範囲で教えてくださる方、
いらっしゃいましたら、よろしくお願いします。

Aベストアンサー

これでどうでしょう。
if文判定、及びwhile文判定を修正しました。

#include <stdio.h>
#include <math.h>
#define f(x)(x*x-2.0)
int main(void)
{
int i=0;
double m,x1=2.0,x2=1.0,eps=1.0e-5;
do{
++i;
m=(x1+x2)/2;
if (f(m)>0)
{
x1 = m;
}
else
{
x2 = m;
}
}
while (fabs(x1-x2)>eps);
printf("%f,%d\n",m,i);
return 0;
}

Qニュートン法を使って解を求めるC言語プログラム

C言語を使って y=x^2-4x のyの解をニュートン法を使って求める
プログラムを作る課題を出されたんですが、ニュートン法が良く分かっていないので、いろいろ調べたり、人に聞いたりしたところ
#include<stdio.h>
#include<math.h>
void main()
{
int counter=0;
double an,g,f,sh=0.0001;
printf("初期値を入力して下さい==>");
scanf("%ld",&an);
do{
g=(an*an)/(2*an-4);
f=2*an-4;
counter++;
}while(fabs(f)>sh);
printf("反復回数 %d 回 y=%lf \n",counter,g);
}
でプログラムがこんな感じになったんですが、結局ニュートン法がどうなのかがわかりません。 なんか微分とかやるとか言われたんですが、工業系の学校で数学の授業が無いので微分についてがわかりません。
このプログラムは、コンパイルはできるんですが、動きません。
ニュートン法についてよくわからないのでどこが間違ってるかわかりません。 ニュートン法についてできるだけ分かりやすく解説してほしいです。

C言語を使って y=x^2-4x のyの解をニュートン法を使って求める
プログラムを作る課題を出されたんですが、ニュートン法が良く分かっていないので、いろいろ調べたり、人に聞いたりしたところ
#include<stdio.h>
#include<math.h>
void main()
{
int counter=0;
double an,g,f,sh=0.0001;
printf("初期値を入力して下さい==>");
scanf("%ld",&an);
do{
g=(an*an)/(2*an-4);
f=2*an-4;
counter++;
}while(fabs(f)>sh);
printf("反復回数 %d 回 y=%lf \n",counter,g);
}
でプログラムがこんな感...続きを読む

Aベストアンサー

ニュートン法を理解するには、せめて微分の初歩の初歩は理解して下さい。
とりあえず、必要なところだけ。

y=x^2-4x
の解をもとめるには、次のようにします。
計算途中の近似解をa(n)とすると、それを元に得られる、より精度の良い近似解a(n+1)は、
a(n+1)=(a(n)*a(n))/(2*a(n)-4)
として求められます。(ニュートン法の理論から)
これを繰り返していって、
|a(n+1)-a(n)| < 0.0001
となったときに、十分精度の良い解が得られたと判断し、計算を終了します。
(計算終了の閾値0.0001は提示されたプログラムから取りました。)

プログラムの間違いは、下記の2点。
誤:scanf("%ld",&an);
正:scanf("%lf",&an);

誤:f=2*an-4;
正:f=g-an; an=g;

上記を修正し、初期値が2より大きい場合は4.000000が、初期値が2未満のときは
0.000000が求められることを確かめて下さい。

Q2分法で方程式の複数の解を自動的に求めるには?

2分法を授業で習い、アルゴリズムは理解できました。
そして、2分法で方程式の解を求めるプログラムも完成したのですが、

3次方程式などの全ての解を2分法で求める場合、本来ならば、
グラフなどを描き、適切な初期値を自分で変更していく必要があると思います。

しかし、方程式の複数の解を自動的に求めたいのです。


もし、2分法で方程式の複数の解を自動的に求めるアルゴリズムがあれば教えていただけないでしょうか。

よろしくお願いします。


※ 私が作成したプログラム(C言語)も載せておきます。

#include <stdio.h>
#include <math.h>

double f(double x)
{
return ((x-1.0)*(x-2.0)*(x-3.0));
}

int main ()
{
int i;
double a,b,x;
double gosa = 1.0e-14;

printf("aの値を入力してください。\n");
scanf("%lf",&a);
printf("bの値を入力してください。\n");
scanf("%lf",&b);

if(f(a)*f(b) >0) printf("aとbの範囲の中に適切な解が存在しません。\n");

while(1){

x = (a+b)/2.0;
printf("%.14f\n",x);

if(fabs(b-a)<gosa) break;

if(f(a)*f(x)<=0){
b = x;
}
else{
a = x;
}

}
return(0);
}

2分法を授業で習い、アルゴリズムは理解できました。
そして、2分法で方程式の解を求めるプログラムも完成したのですが、

3次方程式などの全ての解を2分法で求める場合、本来ならば、
グラフなどを描き、適切な初期値を自分で変更していく必要があると思います。

しかし、方程式の複数の解を自動的に求めたいのです。


もし、2分法で方程式の複数の解を自動的に求めるアルゴリズムがあれば教えていただけないでしょうか。

よろしくお願いします。


※ 私が作成したプログラム(C言語)も載せておきます。...続きを読む

Aベストアンサー

#1 では「一般論的には不可能」と書きましたが, 解くべき方程式が「重解を持たない」実係数代数方程式 (つまり「実係数多項式 = 0」の形) で, かつ「係数を与えている」場合にはすべての実解を見つけることが可能です.

これは二分法では「それぞれの解に対し, その解を (そしてその解だけを) 含む区間を決定する」ことができればよいわけですが, そのためには「与えられた区間にどれだけの解を持つか」がわかれば十分です. もちろんこれ自体が一般には無理ですが, 上の条件を満たせば「Strum列」というものを考えることで可能となります.

詳細は参照URL を見てほしいわけですが, ここで「数式として微分する」という操作が必要なので「係数を与える」ことが条件に入ってきます.

参考URL:http://www.math.meiji.ac.jp/~mk/labo/text/eigen-values/node53.html

Q3次方程式の求解プログラム(ニュートン法)について!

初心者です!
ニュートン法での3次方程式の求解プログラムを作成しようとしています。
ですがよく分かりません(-_-;)
どなたか教えていただけないでしょうか。。。

Aベストアンサー

プログラム書きました。
これで、どうでしょう?

/* 3次方程式の求解 */
#include<stdio.h>
#include<math.h>
#include<float.h>

#define PI 3.14159265358979323846

#define REAL 0 /* 実根 */
#define IMAGE 1 /* 虚数根 */

int main(void){

double a, b, c, d; /* 3次方程式の係数 */
double p, q;
double D;
double x1, x2, x3; /* 根の実部 */
double y1, y2, y3;
double Im; /* 根の虚部 */
double u, v;
double d_u, d_v;
double phi;

int kind; /* 根の種類: REAL, IMAGE */

// ここから
printf("3次方程式(ax^3+bx^2+cx+d=0)の各係数:\n");
printf("a>>>");
scanf("%lf", &a);
printf("b>>>");
scanf("%lf", &b);
printf("c>>>");
scanf("%lf", &c);
printf("d>>>");
scanf("%lf", &d);

// ここまで消して、a, b, c, d値を代入する式を書いてください。

printf("3次方程式(%gx^3%+gx^2%+gx%+g=0)の解は\n", a, b, c, d );
if( a == 0.0 ){
printf("a(%g)がゼロなので,データエラーとみなし,\n", a );
printf("解を求めずに終了します.\n");
return 1; /* 終了コードを1にして,プログラムを終了 */
}

p = ( 3*a*c - b*b ) / ( 9*a*a );
q = ( 2*b*b*b - 9*a*b*c + 27*a*a*d ) / ( 54*a*a*a );

D = q*q + p*p*p; /* Dには誤差が含まれてしまうことに注意 */

if( fabs(D) <= DBL_EPSILON ){ /* Dを数値的にゼロかどうかチェックする */
/* 3つの重根(2重根・3重根)を含む実根 */
y1 = 2*pow(-q, 1.0/3.0);
y2 = y3 = -y1/2;
kind = REAL;
}else if( D < 0 ){ /* 3つの異なる実根 */
phi = acos( -q / pow( -p*p*p, 1.0/3.0 ) );
y1 = 2*sqrt(-p)*cos(phi/3);
y2 = -2*sqrt(-p)*cos(phi/3+PI/3);
y3 = -2*sqrt(-p)*cos(phi/3-PI/3);
kind = REAL;
}else{ /* 1つの実根,2つの共役複素数の解 */
d_u = -q+sqrt(D);
d_v = -q-sqrt(D);

if( d_u >= 0 ) u = pow( d_u, 1.0/3.0 );
else u = -pow( -d_u, 1.0/3.0 );
if( d_v >= 0 ) v = pow( d_v, 1.0/3.0 );
else v = -pow( -d_v, 1.0/3.0 );
y1 = u+v;
y2 = y3 = -y1/2;
Im = sqrt(3)/2*(u-v);
kind = IMAGE;
}

x1 = y1 - b/(3*a);
x2 = y2 - b/(3*a);
x3 = y3 - b/(3*a);

if( kind == REAL ){
printf("x1=%g, x2=%g, x3=%g\n", x1, x2, x3 );
}else{
printf("x1=%g, x2=(%g + %g i), x3=(%g - %g i)\n",
x1, x2, Im, x3, Im );
}

return 0;
}

プログラム書きました。
これで、どうでしょう?

/* 3次方程式の求解 */
#include<stdio.h>
#include<math.h>
#include<float.h>

#define PI 3.14159265358979323846

#define REAL 0 /* 実根 */
#define IMAGE 1 /* 虚数根 */

int main(void){

double a, b, c, d; /* 3次方程式の係数 */
double p, q;
double D;
double x1, x2, x3; /* 根の実部 */
double y1, y2, y3;
double Im; /* 根の虚部 */
double u, v;
double d_u, d_v;
double phi;

int kind; /* 根の種類: REAL, IMA...続きを読む

Q三角関数の記述の仕方

タイトルそのまんまなんですが、三角関数はC言語ではどのように記述すればいいでしょうか?
角度にラジアン表記でπ(パイ)を使いたいんですが、その表記方法もわかりません。
僕の持っている本に載ってなかったので質問させていただきました。
よろしくお願いします。

Aベストアンサー

C言語で三角関数を使うためには、math.h をインクルードする必要があります。使い方は例えば、こんな感じです。

#define M_PI 3.14159265358979 /* 円周率 */

double x, y, theta;

theta = M_PI / 4.0;
x = cos(theta); /* sin,cos,tanの引数は弧度法の角度です。*/
y = sin(theta);

πは上記の例のように自分で定義して使ってください。

Q波長(nm)をエネルギー(ev)に変換する式は?

波長(nm)をエネルギー(ev)に変換する式を知っていたら是非とも教えて欲しいのですが。
どうぞよろしくお願いいたします。

Aベストアンサー

No1 の回答の式より
 E = hc/λ[J]
   = hc/eλ[eV]
となります。
波長が nm 単位なら E = hc×10^9/eλ です。
あとは、
 h = 6.626*10^-34[J・s]
 e = 1.602*10^-19[C]
 c = 2.998*10^8[m/s]
などの値より、
 E≒1240/λ[eV]
となります。

>例えば540nmでは2.33eVになると論文には書いてあるのですが
>合っているのでしょうか?
λに 540[nm] を代入すると
 E = 1240/540 = 2.30[eV]
でちょっとずれてます。
式はあっているはずです。

Q平滑回路の特徴について

(1)平滑回路には、コンデンサインプット形とチョークコイルインプット形がありますが、
コンデンサインプット形は、高電圧が得られるが、電圧変動が大きい
チョークコイルインプット形は、電圧変動が小さいが、高電圧が得られない
とあるのですが、この理由と言うか、回路を見てもなぜそうなるのかがわかりません。両者の特徴についてその原理を教えていただけないでしょうか。

(2)また、平滑回路にさらに直流にするためろ波回路なるものをつけるとあるのですが、どういうものなのでしょうか。

(3)また、このチョークコイルとはどういったコイルなのでしょうか?構造など一般的にいう鉄心に巻きつけたようなコイルとは違うのでしょうか。

Aベストアンサー

1.コンデンサ入力型では直流電圧が(理想的には)整流器出力のピーク値(交流電圧のピーク値)になります。それに対してチョーク入力では(理想的には)平均値になります。(チョークコイルが電圧の脈動分を吸収するため)
結果、コンデンサインプットの方が電圧が高くなります。(単相全波整流で1.5倍くらい)
また、コンデンサ入力では、交流一周期のうち、ダイオードが導通している時間は短くて、大半の期間はコンデンサから負荷電流を供給しています。このため負荷電流が増えるとコンデンサ端子電圧の低下が大きくなって、リプル電圧が増えると同時に平気電圧が下がります。
これにたいしてチョーク入力では、ダイオードが連続して導通していて、電圧低下が抑えられます。(ただし、チョークコイルが有効に働いてダイオードを連続して導通させるためには、コイルに常に電流が流れるよう一定以上の負荷電流を流す必要があります。軽負荷から無負荷の部分では急速に電圧が変化します。)

2.電圧の脈動分を除去する回路です。通常は直流電圧を安定化する回路が同時にフィルタ(ろ波)の機能も持っています。(ちなみに、チョークコイルや平滑コンデンサもろ波回路(の一種あるいは一部)です。

3.直流電流を流せるように作られているコイルです。普通に鉄心にコイルを巻いただけだと、直流電流で鉄心が磁気飽和してコイルとして作用しなくなります。これを防ぐために直流用のコイルでは鉄心の途中にギャップをつけて磁束密度が上がり過ぎないようにしています。

1.コンデンサ入力型では直流電圧が(理想的には)整流器出力のピーク値(交流電圧のピーク値)になります。それに対してチョーク入力では(理想的には)平均値になります。(チョークコイルが電圧の脈動分を吸収するため)
結果、コンデンサインプットの方が電圧が高くなります。(単相全波整流で1.5倍くらい)
また、コンデンサ入力では、交流一周期のうち、ダイオードが導通している時間は短くて、大半の期間はコンデンサから負荷電流を供給しています。このため負荷電流が増えるとコンデンサ端子電圧の低下が...続きを読む

Qがあるのにsqrtが・・・

最初にあるプログラムを作っていたのですが、その祭sqrtでエラーが出てしまったので、別にsqrtを使う短いプログラムを作りました。それが以下のものになります。(test3.c)

#include<stdio.h>
#include<math.h>

int main(void){
int atai;
double x=2.0;
atai=(int)sqrt(x);
printf("atai is %c",atai);
}


sqrtが動作するか確かめる為のものです。このプログラム(test3.c)で以下のエラーが出てしまいました。

/tmp/ccqEejZ1.o(.text+0x4d): In function `main':
test3.c: undefined reference to `sqrt'
collect2: ld はステータス 1 で終了しました

ちなみにLinux(Fedora core 4)を使用しています。
初心者ということもありなぜエラーが出るのか分かりません。
ちなみに<math.h>を使用しないプログラムは普通に動作します。
解決方法をご存知の方がいらっしゃいましたらご教授下さいませ。
よろしくお願いします。

最初にあるプログラムを作っていたのですが、その祭sqrtでエラーが出てしまったので、別にsqrtを使う短いプログラムを作りました。それが以下のものになります。(test3.c)

#include<stdio.h>
#include<math.h>

int main(void){
int atai;
double x=2.0;
atai=(int)sqrt(x);
printf("atai is %c",atai);
}


sqrtが動作するか確かめる為のものです。このプログラム(test3.c)で以下のエラーが出てしまいました。

/tmp/ccqEejZ1.o(.text+0x4d): In function `main':
test3.c: undefined r...続きを読む

Aベストアンサー

コンパイルのオプションつけてないとかないですよね?
たとえばTerminalとかだとコンパイル時に 『-lm』とかつけますが

Qエクセルで計算すると2.43E-19などと表示される。Eとは何ですか?

よろしくお願いします。
エクセルの回帰分析をすると有意水準で2.43E-19などと表示されますが
Eとは何でしょうか?

また、回帰分析の数字の意味が良く分からないのですが、
皆さんは独学されましたか?それとも講座などをうけたのでしょうか?

回帰分析でR2(決定係数)しかみていないのですが
どうすれば回帰分析が分かるようになるのでしょうか?
本を読んだのですがいまいち難しくて分かりません。
教えてください。
よろしくお願いします。

Aベストアンサー

★回答
・最初に『回帰分析』をここで説明するのは少し大変なので『E』のみ説明します。
・回答者 No.1 ~ No.3 さんと同じく『指数表記』の『Exponent』ですよ。
・『指数』って分かりますか?
・10→1.0E+1(1.0×10の1乗)→×10倍
・100→1.0E+2(1.0×10の2乗)→×100倍
・1000→1.0E+3(1.0×10の3乗)→×1000倍
・0.1→1.0E-1(1.0×1/10の1乗)→×1/10倍→÷10
・0.01→1.0E-2(1.0×1/10の2乗)→×1/100倍→÷100
・0.001→1.0E-3(1.0×1/10の3乗)→×1/1000倍→÷1000
・になります。ようするに 10 を n 乗すると元の数字になるための指数表記のことですよ。
・よって、『2.43E-19』とは?
 2.43×1/(10の19乗)で、
 2.43×1/10000000000000000000となり、
 2.43×0.0000000000000000001だから、
 0.000000000000000000243という数値を意味します。

補足:
・E+数値は 10、100、1000 という大きい数を表します。
・E-数値は 0.1、0.01、0.001 という小さい数を表します。
・数学では『2.43×10』の次に、小さい数字で上に『19』と表示します。→http://ja.wikipedia.org/wiki/%E6%8C%87%E6%95%B0%E8%A1%A8%E8%A8%98
・最後に『回帰分析』とは何?下の『参考URL』をどうぞ。→『数学』カテゴリで質問してみては?

参考URL:http://ja.wikipedia.org/wiki/%E5%9B%9E%E5%B8%B0%E5%88%86%E6%9E%90

★回答
・最初に『回帰分析』をここで説明するのは少し大変なので『E』のみ説明します。
・回答者 No.1 ~ No.3 さんと同じく『指数表記』の『Exponent』ですよ。
・『指数』って分かりますか?
・10→1.0E+1(1.0×10の1乗)→×10倍
・100→1.0E+2(1.0×10の2乗)→×100倍
・1000→1.0E+3(1.0×10の3乗)→×1000倍
・0.1→1.0E-1(1.0×1/10の1乗)→×1/10倍→÷10
・0.01→1.0E-2(1.0×1/10の2乗)→×1/100倍→÷100
・0.001→1.0E-3(1.0×1/10の3乗)→×1/1000倍→÷1000
・になります。ようするに 10 を n 乗すると元の数字になるた...続きを読む

QC言語のプログラムが実行できません。

C言語のプログラムが実行できません。

コンパイルは出来るんですが、実行すると、「Segmentation fault」と表示されてしまいます。

これは何のエラーなんでしょうか?
基本的な事かもしれませんが、分かる方宜しくお願い致します。

Aベストアンサー

僕も何度も出したなぁ。

ひとくちにSegmentation faultといっても、それこそさまざまな要因があるので、
これだけで原因を突き止めるのは非常に難しいです。

コンパイルはあくまで文法としてみているだけであり、
処理の流れ、メモリ確保など、プログラムそのものを見ているわけではありません。
このエラーが出るのは文法などよりもっと上位の原因なのです。
たとえばですが。
長さ10の配列があったとして、11番目以降を参照したりすると、
そういうのが出たような気がします。

ですから、変数があれば、その内容をprintf文で逐一出していき、
変な値が入っていないとか、少しずつ直していくしかないと思います。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング