ページ 1 / 1
入試の過去問を解いてみたのですが
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言語で書かれたプログラムのことを意味すると仮定すると、大間違いです。
コンパイルすら通らないでしょう。質問する前に自分でテストを行ってください。
手元に開発環境が無い場合、
Ideoneや
Wandboxなどが役に立つかもしれません。
- εは識別子に使えないかもしれません。変数名には英語のアルファベット、アラビア数字、アンダースコア(すべて半角)のみを用いるべきです。
- 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
ありがとうございます!
解決しました!