ページ 1 / 1
二分法について
Posted: 2017年7月16日(日) 16:36
by Makoto
https://yahoo.jp/box/QL05MW
a=x*x*xだとf(x)に何を代入しても0になって同符号になるから間違っていると考えたのですが、それ以外の考えが思いつきません。この問題を解決できるようにご教授お願いします。
コード:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int xa, xb;
double n, x, a, xm, f(xa), f(xm);
if(argv[1]==NULL)
{
printf("引数が足りません\n");
return 1;
}
n=atoi(argv[1]);
printf("初期区間を入力して下さい\n");
scanf("%d %d", &xa, &xb);
while(xb-xa>=0.000001)
{
xm=((double)xa+(double)xb)/2;
f(xa)=(double)xa*(double)xa*(double)xa-a;
f(xm)=xm*xm*xm-a;
if(f(xa)>=f(xm)>=0 || f(xa)<=f(xm)<=0)
{
xa=xm;
}
else
{
xb=xm;
}
}
printf("%fの立方根は%f\n", n, xm);
return 0;
}
Re: 二分法について
Posted: 2017年7月16日(日) 18:06
by かずま
f(x) = x
3 - a のグラフが書かれていますよね。それを見ると、
f(x
a) < 0
f(x
m) < 0
f(x
b) > 0
になっていますよ。f(x
m) と f(x
b) は異符号です、
C で関数 f(x) の定義は次の通り。
コード:
double a;
double f(double x)
{
return x * x * x - a;
}
Re: 二分法について
Posted: 2017年7月16日(日) 19:25
by Math
根をもとめるのはNewton法とにてますね。考え方はこうですね。(^^;
コード:
#include <stdio.h>
#include <stdlib.h>
double a;
/* 関数定義 */
double f(double x)
{
return x * x * x - a;
}
int main(int argc, char *argv[])
{
double xa, xb, xm; /* int xa, xb; */
/* double n, x, a, xm, f(xa), f(xm);
if (argv[1] == NULL)
{
printf("引数が足りません\n");
return 1;
}
n = atoi(argv[1]);
printf("初期区間を入力して下さい\n");
scanf("%d %d", &xa, &xb); */
a = 27.0; xa = 2.0; xb = 5.0; /* とする。答えは3.0のはず。 */
while (xb - xa >= 0.000001)
{
/* xm = ((double)xa + (double)xb) / 2;
f(xa) = (double)xa*(double)xa*(double)xa - a;
f(xm) = xm*xm*xm - a;
*/
xm = (xa + xb) / 2.0;
printf("%f\n", f(xm));
if (f(xm)*f(xa)<0)
/* if (f(xa) >= f(xm) >= 0 || f(xa) <= f(xm) <= 0) */
{
xb = xm;
}
else
{
xa = xm;
}
}
printf("%fの立方根は%f\n", a, xm);
return 0;
}
コード:
1>------ すべてのリビルド開始: プロジェクト:ConsoleApplication1, 構成: Debug Win32 ------
1>c1.cpp
1>ConsoleApplication1.vcxproj -> D:\z17a\07\16\ConsoleApplication1\Debug\ConsoleApplication1.exe
1>ConsoleApplication1.vcxproj -> D:\z17a\07\16\ConsoleApplication1\Debug\ConsoleApplication1.pdb (Partial PDB)
========== すべてリビルド: 1 正常終了、0 失敗、0 スキップ ==========
コード:
15.875000
-6.203125
3.517578
-1.652588
0.852570
-0.419682
0.211487
-0.105331
0.052769
-0.026359
0.013186
-0.006591
0.003296
-0.001648
0.000824
-0.000412
0.000206
-0.000103
0.000051
-0.000026
0.000013
-0.000006
27.000000の立方根は3.000000
続行するには何かキーを押してください . . .
[/size]
Re: 二分法について
Posted: 2017年7月16日(日) 19:43
by かずま
Math さんが書きました:根をもとめるのはNewton法とにてますね。考え方はこうですね。(^^;
コード:
a = 27.0; xa = 2.0; xb = 4.0; /* とする。答えは3.0のはず。 */
このように xb = 4.0 にすると、実行結果は
コード:
0.000000
15.875000
25.734375
31.185547
34.046631
35.511688
36.252926
36.625732
36.812683
36.906296
36.953136
36.976565
36.988282
36.994141
36.997070
36.998535
36.999268
36.999634
36.999817
36.999908
36.999954
27.000000の立方根は3.999999
3.00000 になりませんね。
オフトピック
sizeタグで文字を小さくするのはなぜですか?
見にくくて仕方がないので、やめてほしいのですが。
Re: 二分法について
Posted: 2017年7月16日(日) 21:09
by Math
>このように xb = 4.0 にすると、実行結果は
そんなの すぐわかるじゃん!
2と4いれたらどんぴしゃ3だから。原理をいっただけなので doループにするか チェック分いれないとね!
完成形にしてあげたら。
Re: 二分法について
Posted: 2017年7月17日(月) 08:05
by かずま
Math さんが書きました:>このように xb = 4.0 にすると、実行結果は
そんなの すぐわかるじゃん!
2と4いれたらどんぴしゃ3だから。原理をいっただけなので doループにするか チェック分いれないとね!
完成形にしてあげたら。
ドンピシャですぐわかる例で、指摘をしたまでです。
a = 27.0, xa = 0.0, xb = 32.0 で、3 がすぐにわかりますか?
a = 125.0, xa = 0.0, xb = 128.0 で、5 がすぐにがわかりますか?
原理として、同符号、異符号、ゼロの場合分けが必要なのです。
ところで、sizeタグの件はどうなっているのですか?
Re: 二分法について
Posted: 2017年7月17日(月) 21:57
by Makoto
画像が見えにくくて、すみません。
https://yahoo.jp/box/R7A38v
教えて頂いたように直しました。しかし立方根の実行結果が、うまくいきませんでした。どの部分に問題があるのか分からないので教えて頂けないでしょうか?
コード:
#include <stdio.h>
#include <stdlib.h>
double f(double x)
{
double a;
return x*x*x-a;
}
int main(int argc, char *argv[])
{
double n, xa, xb, xm;
if(argv[1]==NULL)
{
printf("引数が足りません\n");
return 1;
}
n=atoi(argv[1]);
printf("初期区間を入力して下さい\n");
scanf("%lf %lf", &xa, &xb);
while(xb-xa>=0.000001)
{
xm=(xa+xb)/2;
if(f(xa)*f(xm)>0) //同じ符号の場合
{
xa=xm;
}
else
{
xb=xm;
}
}
printf("%fの立方根は%f\n", n, xm);
return 0;
}
Re: 二分法について
Posted: 2017年7月17日(月) 22:43
by Math
Windows10、VS2017Community、IDE、C言語
コード:
#include <stdio.h>
#include <stdlib.h>
double a; /* Global 変数 */
double f(double x)
{
return x*x*x - a;
}
int main(int argc, char *argv[])
{
double n, xa, xb, xm;
/*
if (argv[1] == NULL)
{
printf("引数が足りません\n");
return 1;
}
*/
n = (double)atoi("5"); /* n =(double) atoi(argv[1]); */
a = n;
printf("初期区間を入力して下さい\n");
scanf("%lf %lf", &xa, &xb);
while (xb - xa >= 0.000001)
{
xm = (xa + xb) / 2;
if (f(xa)*f(xm)>0) //同じ符号の場合
{
xa = xm;
}
else
{
xb = xm;
}
}
printf("%fの立方根は%f\n", n, xm);
return 0;
}
コード:
1>------ ビルド開始: プロジェクト: ConsoleApplication6, 構成: Debug Win32 ------
1>c1.c
1>d:\z17a\07\16\consoleapplication6\consoleapplication6\c1.c(24): warning C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>c:\program files (x86)\windows kits\10\include\10.0.15063.0\ucrt\stdio.h(1272): note: 'scanf' の宣言を確認してください
1>ConsoleApplication6.vcxproj -> D:\z17a\07\16\ConsoleApplication6\Debug\ConsoleApplication6.exe
1>ConsoleApplication6.vcxproj -> D:\z17a\07\16\ConsoleApplication6\Debug\ConsoleApplication6.pdb (Partial PDB)
1>プロジェクト "ConsoleApplication6.vcxproj" のビルドが終了しました。
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========
コード:
初期区間を入力して下さい
1
3
5.000000の立方根は1.709975
続行するには何かキーを押してください . . .
わかりますよね(^^;
Re: 二分法について
Posted: 2017年7月17日(月) 22:44
by みけCAT
Makoto さんが書きました:どの部分に問題があるのか分からないので教えて頂けないでしょうか?
関数fで使われている自動変数aが明示的に初期化されていないので、値は不定になっています。
main関数のnの値を何らかの方法で関数fに伝え、それを用いた計算をさせないといけませんね。
オフトピック
画像にあるサンプル入力に対してなら大丈夫そうだけど、本当にatoiでいいのかなあ…?
Re: 二分法について
Posted: 2017年7月20日(木) 12:06
by かずま
Makoto さんが書きました:教えて頂いたように直しました。しかし立方根の実行結果が、うまくいきませんでした。どの部分に問題があるのか分からないので教えて頂けないでしょうか?
教えたとおりに直していません。
doube a; の位置が違います。
これは、どこに書いても同じだと思っているんですか?
関数の中と外とでは大違いです。もう分かりましたか?
分かったのなら、どういうことか説明してください。
分からなかったのなら、質問してください。
それから、a = atof(argv[1]); のほうがいいでしょう。