ページ 11

この問題わかる方・・・

Posted: 2007年6月19日(火) 21:09
by C言語が苦手な人
1.キーボードから数値を入力する。
2.その数値で1を割り逆数を求める
3.その結果が割り切れたら答えを表示する。
  割り切れずに循環したら途中まで表示し、循環節も表示する。
といった内容のプログラムなのですがさっぱり分かりません。構造体を使って余りの値を入れていって、1桁計算するたびに、今まで記憶した値と同じでないか調べ、同じ値になったら循環という風にやるらしいのですが…
どなたか分かる方回答よろしくお願いいたします。

Re:この問題わかる方・・・

Posted: 2007年6月19日(火) 21:41
by 管理人
1~3では難易度が違うようですが、どの辺まで今出来ていますか?
どの辺でつまっていますか?

Re:この問題わかる方・・・

Posted: 2007年6月19日(火) 22:11
by C言語が苦手な人
回答ありがとうございます。
値を入力するのと表示するのはできると思うのですが、2と3の計算のところがわからないです。
よろしくお願い致します。

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 01:24
by Justy
>2と3の計算のところがわからないです
 ググルと計算方法は出てきます。
 特に桁数を求める方の直ぐに出てきます。
 
 処理の順番としては、循環しているなら循環の開始と終了の位置を求めます。

 循環していなくても小数点以下何桁(終了位置)になるかを調べます。
 で、次に求めた終了位置の桁まで除算を行います。

 あとはその結果を終了位置まで表示するだけです。
 その際、循環していたのなら、[....]などでその部分が循環していることを表示すれば完成です。


 結果の検証の方はこのサイトを参考にするといいでしょう。

素数大好き
http://homepage2.nifty.com/hiranouchi/p ... ation.html



 ・・・・って、これ結構難易度高めですよ。
 除算の結果が小数点以下十桁以上になることがほとんどなので
double型では扱いきれず、その為動的をバッファも作らないと
いけないですし、除算自体も自前で計算しないといけません
(といってもその計算のアルゴリズム自体は小学生レベルの計算ですが)。

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 04:42
by フリオ
 
>  除算の結果が小数点以下十桁以上になることがほとんどなので
> double型では扱いきれず、その為動的をバッファも作らないと

 結果を保存する場合は工夫が必要ですが、表示するだけなら
筆算の要領で、一桁づつ表示していけば、"int"で処理できます。
 

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 05:41
by C言語が苦手な人
回答ありがとうございました。
参考にさせていただきたいと思います。
また何か質問させていただくかもしれないのでそのときはよろしくお願い致します。

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 10:29
by フリオ
 
 どう解決したのか、書いてほしかった。


 入力は、チェックしてません。
#include <stdio.h>
#include <stdlib.h>

typedef struct fraction{
		int dvnd;
		int dvsr;
		int sign;
	}FRACTION;

int GCD(int num0, int num1)
{
	if(!num1) return num0;
	return GCD(num1, num0 % num1);
}

int SetFrac(FRACTION *frac)
{
	int dvnd, dvsr, gcd;
	
	printf("\n被除数 : ");
	scanf("%d", &dvnd);
	printf(" 除数  : ");
	scanf("%d", &dvsr);
	if(!dvsr) return 0;
	if(!dvnd) frac->sign = 0;
	else frac->sign = (dvnd < 0) ^ (dvsr < 0);
	dvnd = abs(dvnd);
	dvsr = abs(dvsr);
	gcd = GCD(dvnd, dvsr);
	frac->dvnd = dvnd / gcd;
	frac->dvsr = dvsr / gcd;
	return 1;
}

int Fact2or5(int num)
{
	int i, j;
	
	for(i = 0; !(num % 2); i ++) num /= 2;
	for(j = 0; !(num % 5); j ++) num /= 5;
	if(i < j) return j;
	return i;
}

int main(void)
{
	FRACTION frac;
	int dvnd, remain, dplace = 0, unrepeat;
	
	if(!SetFrac(&frac)){
		puts("除数は 0 以外の整数を入れて下さい");
		return 1;
	}
	printf("\n商 :: ");
	if(frac.sign) putchar('-');
	printf("%d", frac.dvnd / frac.dvsr);
	if(frac.dvsr == 1) puts("\n (小数部無し)");
	else{
		dvnd = frac.dvnd % frac.dvsr;
		putchar('.');
		unrepeat = Fact2or5(frac.dvsr);
		do{
			if(++ dplace == (unrepeat + 1)){
				remain = dvnd;
				putchar('[');
			}
			printf("%d",(dvnd * 10) / frac.dvsr);
			dvnd = (dvnd * 10) % frac.dvsr;
		}while(dvnd && dvnd != remain);
		if(dplace != unrepeat) putchar(']');
		printf("\n否循環部 %d 桁、循環部([/url]内) %d 桁\n", unrepeat, dplace - unrepeat);
	}
	return 0;
}
 

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 12:25
by Justy
>結果を保存する場合は工夫が必要ですが、表示するだけなら
>筆算の要領で、一桁づつ表示していけば、"int"で処理できます
 ルーチンを思い浮かべたときに、計算と表示を分離していたので、
そう書いたのですが、たしかに計算しながら表示すればバッファは不要ですね。


 あ、で上のプログラムですが、main関数の remain変数が未初期化のまま
whileで参照されるケースがあるのですが、それは意図した通りでしょうか?
 1を 1234で割ったときとか。

Re:この問題わかる方・・・

Posted: 2007年6月20日(水) 21:02
by フリオ
 
>  あ、で上のプログラムですが、main関数の remain変数が未初期化のまま
> whileで参照されるケースがあるのですが、それは意図した通りでしょうか?

 ミスです。

do{
・・・
}while(dvnd && dvnd != remain);

を、

remain = 0;
while(dvnd != remain){
・・・
}

に、訂正。
お粗末でした。_(_ _)_