二分法について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Makoto

二分法について

#1

投稿記事 by Makoto » 8年前

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: 二分法について

#2

投稿記事 by かずま » 8年前

Makoto さんが書きました:https://yahoo.jp/box/QL05MW
a=x*x*xだとf(x)に何を代入しても0になって同符号になるから間違っていると考えたのですが、それ以外の考えが思いつきません。
f(x) = x3 - a のグラフが書かれていますよね。それを見ると、
 f(xa) < 0
 f(xm) < 0
 f(xb) > 0
になっていますよ。f(xm) と f(xb) は異符号です、

C で関数 f(x) の定義は次の通り。

コード:

double a;

double f(double x)
{
    return x * x * x - a;
}

Math

Re: 二分法について

#3

投稿記事 by Math » 8年前

根をもとめるのは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: 二分法について

#4

投稿記事 by かずま » 8年前

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タグで文字を小さくするのはなぜですか?
見にくくて仕方がないので、やめてほしいのですが。

Math

Re: 二分法について

#5

投稿記事 by Math » 8年前

>このように xb = 4.0 にすると、実行結果は
そんなの すぐわかるじゃん!

2と4いれたらどんぴしゃ3だから。原理をいっただけなので doループにするか チェック分いれないとね!
完成形にしてあげたら。

かずま

Re: 二分法について

#6

投稿記事 by かずま » 8年前

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タグの件はどうなっているのですか?

Makoto

Re: 二分法について

#7

投稿記事 by Makoto » 8年前

画像が見えにくくて、すみません。
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;
}

Math

Re: 二分法について

#8

投稿記事 by Math » 8年前

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
続行するには何かキーを押してください . . .
わかりますよね(^^;

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 二分法について

#9

投稿記事 by みけCAT » 8年前

Makoto さんが書きました:どの部分に問題があるのか分からないので教えて頂けないでしょうか?
関数fで使われている自動変数aが明示的に初期化されていないので、値は不定になっています。
main関数のnの値を何らかの方法で関数fに伝え、それを用いた計算をさせないといけませんね。
オフトピック
画像にあるサンプル入力に対してなら大丈夫そうだけど、本当にatoiでいいのかなあ…?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 二分法について

#10

投稿記事 by かずま » 8年前

Makoto さんが書きました:教えて頂いたように直しました。しかし立方根の実行結果が、うまくいきませんでした。どの部分に問題があるのか分からないので教えて頂けないでしょうか?
教えたとおりに直していません。
doube a; の位置が違います。
これは、どこに書いても同じだと思っているんですか?
関数の中と外とでは大違いです。もう分かりましたか?
分かったのなら、どういうことか説明してください。
分からなかったのなら、質問してください。

それから、a = atof(argv[1]); のほうがいいでしょう。

返信

“C言語何でも質問掲示板” へ戻る