ページ 11

入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 13:36
by morokosiQ
これであってますでしょうか?

http://i.imgur.com/RKxB8fO.png (問題)

コード:

double func( double X0 )
	{
	double X ;
	double ε=0.000001 ; /* 自分で設定した許容誤差です。*/
	X = (-aX0^2+ab^2+c)/2a(b-X0); /*接線のX切片の値*/
	
	while(X0-X=0)
		{
		X = (-aX0^2+ab^2+c)/2a(b-X0); /*接線のX切片の値*/
		if(X0-X<ε)
			{
			return X ;
			}
		X=X0;
		}
	}
		

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 13:40
by morokosiQ
code訂正します。

コード:

double func( double X0 )
	{
	double X ;
	double ε=0.000001 ; /* 自分で設定した許容誤差です。*/
	
	while(X0-X=0)
		{
		X = (-aX0^2+ab^2+c)/2a(b-X0); /*接線のX切片の値*/
		if(X0-X<ε)
			{
			return X ;
			}
		X=X0;
		}
	}
		

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 14:01
by みけCAT
morokosiQ さんが書きました:これであってますでしょうか?
問題文中の「Cプログラム」が自分の知っているC言語で書かれたプログラムのことを意味すると仮定すると、大間違いです。
コンパイルすら通らないでしょう。質問する前に自分でテストを行ってください。
手元に開発環境が無い場合、IdeoneWandboxなどが役に立つかもしれません。
  • εは識別子に使えないかもしれません。変数名には英語のアルファベット、アラビア数字、アンダースコア(すべて半角)のみを用いるべきです。
  • aX0、abの定義がありません。掛け算には*演算子を用いるべきです。
  • ^演算子はxorを表し、実数には使えないかもしれません。例えばX0の2乗を計算するには素直にX0*X0と書くべきでしょう。
  • 「2a(b-X0)」は一見関数2aの呼び出しに見えますが、2aのような先頭に数字がある文字列は識別子には使えません。掛け算には*演算子を用いるべきです。
  • =は代入演算子です。等しいかどうかの判定には==演算子を用いるとよいでしょう。また、浮動小数点数の誤差による誤動作を避けるため、「差の絶対値が(適当な小さい数)未満なら等しいとみなす」という実装もいいかもしれません。
  • 最初に「X0-X=0」が成立しなかった場合、もしコンパイルエラーがなかったとしても、Xの値が返りません(返る値が不定または0になります)。
  • もしコンパイルエラーがなかったと仮定すると、最初に不定の値Xを用いた計算がされます。結果が意図しないものになるかもしれません。(わざわざ訂正してさらに劣化させましたか…)
また、(2)の答案が見当たらないですね。

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 14:45
by morokosiQ

コード:

#include <stdio.h>

double func( double X0 )
	{
        int a =3; /*仮定*/
        int b=3;    /*仮定*/
        int c= -3;  /*仮定*/	
	double E=0.000001 ; /* 自分で設定した許容誤差です。*/
	double X = (-a*X0*X0+a*b*b+c)/2*a*(b-X0); /*接線のX切片の値*/
      

	while(X0-X==0)
		{
		X = (-a*X0*X0+a*b*b+c)/2*a*(b-X0); /*接線のX切片の値*/
		if(X0-X<E)
			{
                        printf("%d\n",X);
			return X ;
			}
		X=X0;
		}
	}


int main (void){
       
        func(3);
        printf("%d\n",X);

}

これをcodepad( http://codepad.org/ )で通したのですが、失敗しました。


(2)の解答は
元の関数f(x)のx切片を求める計算をしている。 です。

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 14:47
by Tatu
x切片の計算は合っているのでしょうか?

g(x)=f'(x0)(x-x0)+f(x0)
でg(x)=0となるxをf(x0),f'(x0)を用いて表現してみてください。

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 15:56
by box
morokosiQ さんが書きました:

コード:

	double X = (-a*X0*X0+a*b*b+c)/2*a*(b-X0); /*接線のX切片の値*/
		X = (-a*X0*X0+a*b*b+c)/2*a*(b-X0); /*接線のX切片の値*/
この2つの式で、分母の範囲はどこからどこまでであることを想定されていますか?

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月19日(日) 17:20
by みけCAT
  • 5行目に全角スペースがあります。消してください。
  • 「定数a,b,cはこの関数の外側で定義されているとしてよい」という条件なので、
    a,b,cの定義は「double func( double X0 )」の上に書いた方がいいかもしれません。
    (「としてよい」なので間違ってはいないと思いますが、色々な入力に対応できる方がいい気がします)
  • while文の繰り返し条件は妥当ですか?そもそもここで条件判定することは本当に必要ですか?
  • 「X0-X<E」という条件は収束判定として妥当でしょうか?例えばX0=-10000としたらどうなるでしょうか?
  • printfの書式とデータ型が合っていません。double型の値を出力するには%fや%gなどを使用してください。
  • main関数で使用されているXの定義が無いようです。
オフトピック
x0にはb以外の任意の実数が入力されるとする (bは入力されないとは言ってない)

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月20日(月) 12:44
by Tatu

コード:

#include <stdio.h>

double func( double X0 )
{
	//a,b,cは実数なのでintではなく、doubleの方がよい
	//全角スペースを除去
	double a=3.0; /*仮定*/
	double b=3.0; /*仮定*/
	double c=-3.0;/*仮定*/
	double E=0.000001 ; /* 自分で設定した許容誤差です。*/

	double X;

	//条件判定をしない
	while(1)
	{
		//分母を括弧でくくる必要がある
		//X = X0-(a*(X0-b)*(X0-b)+c)/(2*a*(X0-b));でもよい
		X = (-a*X0*X0+a*b*b+c)/(2*a*(b-X0)); /*接線のX切片の値*/
		//|X0-X|<E <=> -E<X0-X かつ X0-X<E
		//math.hをインクルードしてfabsを使って書いてもよい
		if(X0-X<E && X0-X>-E)
		{
			//Xは実数なので整数用の%dではなく、%lfを使用
			printf("%lf\n",X);
			return X ;
		}
		//前のX切片の値を記憶する。X=X0だと意味がない。
		X0=X;
	}
}
 
 
int main (void)
{       
	//bを3.0としているのでそれ以外を引数に入れる
	func(5.0);
	return 0;
}

Re: 入試の過去問を解いてみたのですが

Posted: 2015年7月22日(水) 16:32
by morokosiQ
ありがとうございます!

解決しました!