プロが教える店舗&オフィスのセキュリティ対策術

(1)キーボードから,分子,分母に相当する整数2つを入力し,その既約分数を表示せよ。
(2)分母が1の時には,分子のみを表示する。
(3)分子と分母の符号が異なるときにのみ,-符号を表示する。
(4)分母がゼロの入力エラーに対しては、再入力するように促す。
(5)分子と分母の最大公約数も求めて表示する。
(6)また、正しく計算できる最大規約分数を示せ。

#include <stdio.h>
int main(void)
{
int a,b,i=1,x,y,z;

printf("分子=");/*分子の入力*/
scanf("%d",&a);

printf("分母=");/*分母の入力*/
scanf("%d",&b);

if(b==0)
{
printf("分母が0です。入力が誤っています。\n");
return 0;
}

if(b==1)
{
printf("既約分数は %d\n",a);
return 0;
}

while((i<=a)&&(i<=b))
{
if((a%i==0)&&(b%i==0))
{
x=i;i=i+1; /*xを上書きしていく*/
}
else
{
i=i+1;
}
}
printf("分子と分母の最大公約数=%d より\n",x);

y=a/x;
z=b/x;

printf("既約分数は %d/%d\n",y,z);

return 0;
}

大学の課題で出されたものです。(1)(2)(4)(5)はできたのですが、(3)と(6)の部分のやり方がいまいちよくわからなかったので質問しました。
どなたかご教授お願いできないでしょうか・・・。

A 回答 (6件)

/*


暗に結構コード書いて下さい、って丸投げする質問者ってのも多いんだけど, 質問者さんはそうじゃないみたいで安心した。
きっとこんなコードも読めるんじゃないかな?
*/

#include <stdio.h>
#include <math.h>

/*
abs(x)はxの絶対値を返す関数で,math.hに定義されているんだよ。
もしこれがなくても自分で作れると思う。
*/

int main(void){

int denominator; /* 分母の絶対値 */
int numerator; /* 分子の絶対値 */

int sign;
int gcdofthetwo;

printf("denominator = ");
scanf("%d",&denominator);

printf("numerator = ");
scanf("%d",&numerator);

if(denominator==0){
printf("error : denominator should not be 0. program will exit.\n");
return 0;
}
if (numerator==0){
printf("0");
return 0;
}

gcdofthetwo = gcd(abs(numerator),abs(denominator));

/*
numerator * denominatorがオーバーフローするかも、っていうのが怖いから
(numerator * denominator) / (abs(numerator) * abs(denominator))
って書かずにそれぞれ分割しているんだ
*/

sign = (numerator / abs(numerator)) * (denominator / abs(denominator));

/* 前回のコードで忘れてた最大公約数*/

printf ("gcd:%d\n", gcdofthetwo);
if (abs(denominator) / gcdofthetwo != 1){
printf("answer:%d / %d\n" ,sign * abs(numerator) / gcdofthetwo , abs(denominator) / gcdofthetwo );
}else{
printf("answer:%d\n" ,sign * abs(numerator) / gcdofthetwo );
}
}

int gcd(int a,int b){
/* ユークリッド互除法 */
int retval;
if( (a <= 0) || (b <= 0) ){
return -1;
}

retval = a % b;
while (retval != 0){
a = b;
b = retval;
retval = a % b;
}

return b;

}
    • good
    • 0
この回答へのお礼

2つもプログラムを書いて頂いて恐縮です。
上記のプログラムを見て、書き方が違うだけでとてもシンプルにまとめられるのだなぁと感じ、とても勉強になりました。

課題のほうも無事終えることができました。分かりやすい説明やプログラムまで書いてもらって、今回は本当にお世話になりました。有難うございます。

お礼日時:2008/07/13 22:06

#5を修正



最初戻り値にするつもりでretvalって変数用意したんだけど
return b;って書いているから変数名がおかしい。

ので,変数名はremainderあたりのほうがいいと思う
    • good
    • 0

>#1お礼



if (sign = 1)

if (sign == 1)
の違い解る?
    • good
    • 0
この回答へのお礼

if (sign = 1)

if (sign == 1)
の違い解る?

>>そういえば忘れていました・・・。
if文の条件を表す部分で「=(等しい)」を表すには「==」と書く、という決まりあったような。以後は気をつけます。

お礼日時:2008/07/13 21:53

コード修正



if ( rawnumerator / rawdenominator < 0){

if ( (double)rawnumerator / (double)rawdenominator < 0){
    • good
    • 0

全体の流れはこんな感じでしょうか。


・aとbを入力
・bが0ならエラー表示
・aとbの符号が異なるか調べて符号用変数をセット
 → (aが負)かつ(bがゼロか正)、または、(aが正かゼロ)かつ(bが負)なら符号が異なる(0は正の扱いとしておく)
 →符号が異なるときは符号用変数を-1、符号が同じなら0をセット
・以降の計算は、aもbも正数にして行なう。
・約分の計算(分子と分母を最大公約数で割る)
・符号用変数が-1なら分子をマイナスにする。
・分母が1なら分子だけ表示、そうでなければ分子と分母を表示
    • good
    • 0

/*


質問文をベースを活かすと効率は悪いがこうなる。
変数名変えまくっている。
表示内容を英語にしているのは,書いているのがUTF-8のコードで
gccでコンパイルして
コマンドプロンプト(Shift_JIS)で日本語表示すると化けるから

質問文と違い, 分母 = 2,分子 = 4を入力した場合 4/2ではなく 2と表示する。
質問文と違い, 分母 = 0,分子 = 4を入力した場合 0/4ではなく 0と表示する。

効率的にやるなら
公約数を求める部分を別な関数に分けるし,
math.hを利用してabs関数を用いたりする。
三項演算子も使うかもしれない

*/

#include <stdio.h>
int main(void){

int rawdenominator; /* 分母 */
int rawnumerator; /* 分子 */


int absdenominator; /* 分母の絶対値 */
int absnumerator; /* 分子の絶対値 */


int i; /* カウンタ */
int gcd; /* 分母の絶対値と分子の絶対値の公約数 */

int sign;
printf("denominator = ");
scanf("%d",&rawdenominator);

printf("numerator = ");
scanf("%d",&rawnumerator);

if(rawdenominator==0){
printf("error : denominator should not be 0. program will exit.\n");
return 0;
}
if (rawnumerator==0){
printf("0");
return 0;
}

if (rawnumerator < 0){
absnumerator = -rawnumerator;
}else{
absnumerator = rawnumerator;
}

if (rawdenominator < 0){
absdenominator = -rawdenominator;
}else{
absdenominator = rawdenominator;
}

if (rawnumerator / rawdenominator < 0){
sign = -1;
}else{
sign = 1;
}

i = 1;
gcd = 1;

while((i<=absnumerator)&&(i<= absdenominator)){
if((absnumerator % i==0) && (absdenominator % i==0)){
gcd=i;i=i+1;
}else{
i=i+1;
}

}

if (gcd == absdenominator){
if (sign >= 0){
printf("%d",absnumerator / absdenominator);
}else{
printf("- %d",absnumerator / absdenominator);
}
return 0;

}else{
if (sign >= 0){
printf("%d / %d",absnumerator / gcd ,absdenominator / gcd);
}else{
printf("- %d / %d",absnumerator / gcd ,absdenominator / gcd);
}
return 0;
}



}
    • good
    • 0
この回答へのお礼

わざわざ長いプログラムまで書いてもらってお手数をおかけしました。とても勉強になりました。
1つ質問があるのですが


if (gcd == absdenominator){
if (sign >= 0){
printf("%d",absnumerator / absdenominator);
}else{
printf("- %d",absnumerator / absdenominator);
}
return 0;


場合わけの部分でif (sign >= 0)となっていますがif (sign =1)とするとうまく表示されなくなりました。ソース上ではsignは1か-1のどちらかなので>=0を=1にしてもいいのではと考えたのですが・・・。何か理由があるのでしょうか?

お礼日時:2008/07/12 21:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています