• ベストアンサー

2つ分数の四則演算を行うプログラム

yama5140の回答

  • yama5140
  • ベストアンサー率54% (136/250)
回答No.5

>桁が大きい数で計算しようとすると値がおかしくなってしまいます。    ・今回の質問では、標準入力からの分母と分子は int なので、内部では、-2147483648 ~ 2147483647 と「正しく」扱われる。  ・この分母、分子を「計算(かけ算、たし算)しよう」とした時、「おかしく」なる。    例)2147483647 + 1 = -2147483648  -1 * -2147483648 = -2147483648  ・「おかしく」なる理屈は、分母、分子、丸ごとスタックにおくられ、演算が行われる際に、有限のスタック(今回は32ビット)に【納めきれなくなる】。   ☆そんなら、丸ごとスタックにやらず、1桁ずつ「計算」をすればよいのでは・・。  例えば、筆算で、     123  ×234    の計算をするとき、まず3×4をやって12の2を・・と下位から1桁ずつ確定していきますよね。  この過程をコード化すればよいのではと・・。    で重要なのは、この結果は、「表示」にしか用いない(というか用いられない)。  今回の質問内容では、これで十分ですよね↑・・。  巷のπの計算だって、何万桁まで「内部で扱う数」としてでなく、「結果表示」でのみ有効なものですよね。  でないと、正しいか検証もできないし・・。 ------------------------------------------------ ★「足し算」、「かけ算」について、筆算もどきのソースを投稿します(BorlandC++5.6.4)。  「値がおかしくなって」しまう数で呼び出してみて下さい。 ・「足し算」は、オーバーフローするか判定し、するものについて筆算もどきしてます。   判定:「演算」で、正+正が負のとき、負+負が正のときをオーバーフローとしています。 ・「かけ算」は、上述の方法です。 共に、20個の配列(20桁)で「筆算もどき」しています。 ------------------------------------------- #include <stdio.h> #include <stdlib.h> void Output( char cKekka[] ) {  int i, iSumi = 0;  for( i = 0; i <= 20; i++ ){   if( ( 0 == iSumi ) && ( 0x00 == cKekka[ i ] ) ) continue;   printf( "%c", ( 0x30 + cKekka[ i ] ) );   iSumi = 1;  }  printf( "\n" ); } void Tashizan( int iVal1, int iVal2 ) {  int iOver = 0, kk = 20, iDum;  char cKekka[32] = { 0x00 };  if( iVal1 <= 0 ){ // オーバーフロー判定   if( iVal2 < 0 ){ // 双方負    iOver = iVal1 + iVal2;    if( iOver >= 0 ) iOver = 1;   }  }  if( iVal1 > 0 ){ // オーバーフロー判定   if( iVal2 > 0 ){ // 双方正    iOver = iVal1 + iVal2;    if( iOver <= 0 ) iOver = 2;   }  }  if( ! iOver ){ // オーバーフローしない:通常「演算」   printf( "%d\n", ( iVal1 + iVal2 ) );  }  if( iOver ){ // オーバーフローするので筆算もどき   while( iVal1 || iVal2 ){ // 1桁ずつの足し算    iDum = cKekka[ kk ];    iDum += abs( iVal1 % 10 ); // 下1桁    iDum += abs( iVal2 % 10 );    cKekka[ kk ] = (char)( iDum % 10 );    cKekka[ kk - 1 ] = (char)( iDum / 10 ); // 繰り上がり    kk--; // 上位の桁へ    iVal1 /= 10;    iVal2 /= 10;   }   if( 1 == iOver ) printf( "-" );   Output( cKekka );  } } void Kakezan( int iVal1, int iVal2 ) {  int i, j, kk, iTotal = 0;  char c1[ 32 ] = { 0x00 }, c2[ 32 ] = { 0x00 };  char cKekka[ 32 ] = { 0x00 };  if( iVal1 < 0 ) c1[ 31 ] = 0x01; // 負  if( iVal2 < 0 ) c2[ 31 ] = 0x01;  for( i = 20; i >= 0; i-- ){ // 1桁ずつ配列へ   c1[ i ] = (char)abs( iVal1 % 10 );   c2[ i ] = (char)abs( iVal2 % 10 );   iVal1 /= 10;   iVal2 /= 10;  }  for( i = 20; i >= 0; i-- ){ // 下位から筆算もどき   for( j = 20; j >= 0; j-- ){ // 被乗数桁    kk = j - ( 20 - i ); // 格納桁    if( ( kk - 1 ) <= 0 ) break;    cKekka[ kk ] += (char)( c1[ j ] * c2[ i ] );    cKekka[ kk - 1 ] += (char)( cKekka[ kk ] / 10 ); // 繰り上がり    cKekka[ kk ] = (char)( cKekka[ kk ] % 10 );    iTotal += cKekka[ kk ];   }  }  cKekka[ 31 ] = (char)( c1[ 31 ] + c2[ 31 ] ); // 符号:奇数なら負  if( iTotal && ( cKekka[ 31 ] % 2 ) ) printf( "-" );  if( 0 == iTotal ) printf( "0" );  Output( cKekka ); } 注:インデントに全角空白を用いています。タブに一括変換して下さい。

zinrong
質問者

お礼

回答ありがとうございます。課題のほうですが、何とか終わらせることができましたので、お書き頂いたプログラムはこれからの学習に役立てていきたいとます。

関連するQ&A

  • 既約分数の表示プログラム

    (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の値と(整数値)bの値をキーボードから入力して、そこから、a/bという分数を作るプログラムを書きたいと思います。(符号や約分も考えた形にする) 僕は、ヒントを参考に以下のようなプログラムを書いたのですが、ある条件の下では、正しく動きません。 ・aの値が負の場合 ・aもbも負の値の場合 など・・・ #include <stdio.h> #include <math.h> int main ( void ) { int a,b; int k,min,sign; printf("a=?");scanf("%d",&a); printf("b=?");scanf("%d",&b); if (a*b<0) sign = -1; else sign = 1; a = sign*a ; b = sign*b; if (abs(a)>abs(b)) min = b; else min = abs(a); for ( k=2 ; k<=min ; k++){ if (min%k == 0){ a = a/k; b = b/k; } } printf("a/b = %d",a); if (b != 1) printf("/%d\n",b); else printf("\n"); return 0; } これをどのように修正すれば、正確な答えが出るのでしょうか? 教えてください。

  • C言語における複素数の四則演算について

    複素数の四則演算(a+biとc+diの四則演算)について、for文を用いて表示するプログラムについて、???の部分に何を入れたらよいかわからず、うまく実行することができません。和・差・積・商の計算種別を入れるみたいなのですが、何を入れたらいいのかわかりません。 #include <stdio.h> void fukuso(double a,double b,double c,double d,double *e,double *f,int keisan); int main(void) { double a=4, b=8, c=4, d=3, e, f; int i; for(i=1;i<5;i++){ fukuso(a,b,c,d,&e,&f,???); if(i==1) printf("和演算\n"); else if(i==2) printf("差演算\n"); else if(i==3) printf("積演算\n"); else printf("商演算\n"); printf("e=%f f=%f i\n",e,f); } return (0); } void fukuso(double a1,double b1,double a2,double b2,double *a3,double *b3,int keisan) { if(keisan==1){ *e=a+c; *f=a+c; } else if(keisan==2){ *e=a-c; *f=b-d; } else if(keisan==3){ *e=a*c-b*d; *f=a*d+c*b; } else{ *e=(a*c+b*d)/(c*c+d*d); *f=(-a*d+c*b)/(c*c+d*d); } }

  • このプログラム見てほしいです!!

    #include <stdio.h> int gcd2(int a, int b) { if (!b) return a; return gcd2(b, a%b); } int main() { int a, b, c; printf("2つの任意の整数を入力せよ:"); scanf("%d %d",&a,&b); c=gcd2(a,b); printf("最小公倍数は%d\n",a*b/c); printf("最大公約数は%d\n",c); return 0; } で、最小公約数を出すことはできたのですが、全ての公約数を表示させたいんです!!どうやったらいいのでしょうか??プログラミングまだ初心者なので、ちょっと行き詰ってしまいました。。。 お時間があればでいいのですが、もう一つわからないプログラムがあります。 自然数nを入力し、x^2+y^2=z^2 (x<y)を満たすようなn以下の自然数の組(x,y,z)がいくつあるのかを出力するプログラムなのですが、全くわからず行き詰っています。。どなたかお時間があれば教えて頂きたいです。 色々と申し訳ありません。お願いします(__)

  • 分数の足し算をさせるプログラムが分かりません。どなたか分かりませんか?

    分数の足し算をさせるプログラムが分かりません。 C言語の問題で分数の足し算までは一応できるんですが、答えがでたときに整数で出すやり方と約分して表す方法が分かりません。 どなたか知恵を貸してくれませんか? ユーザから4つの整数を入力し、はじめに入力された2個の整数と後に入力された2個の整数を分数と考え、その分数の和を表示するプログラムを作成せよ。 例えば、「3」「4」「5」「6」と入力されたときは、3/4 + 5/6を計算する。 そのプログラム内では分数の和を計算する関数を作成する。 さらに、 約分を行う関数を 再帰呼び出しを利用して作成する。 void yakubun(int *a1, int *a2) 例えば、以下の場合1/2と表示される。 int i=10,j=20; yakubun(&i,&j); printf(“%d / %d”, i, j); ちなみにここまでできました↓ #include<stdio.h> void bunsu_tasizan(int a1,int a2,int b1,int b2, int *c1,int *c2 ) { *c1=(a1*b2)+(b1*a2); *c2=(a2*b2); } int main() { int x1,x2,y1,y2,z1,z2; printf("整数を入力してください"); scanf("%d",&x1); scanf("%d",&x2); scanf("%d",&y1); scanf("%d",&y2); if(x2==0||y2==0||x2==0&&y2==0) printf("0以外を入力してください"); else{ bunsu_tasizan(x1,x2,y1,y2,&z1,&z2); printf("%d/%d",z1,z2);} return (0); }

  • 整数を3つ読み込み、一番大きいものを表示するプログラム

    3つが違う数であるとしてこうしたんですが、 #include<stdio.h> int main() {int a,b,c; scanf("%d",&a); scanf("%d",&b); scanf("%d",&c); if(a>b && a>c){ printf("%d\n",a);} if(b>a && b>c){ printf("%d\n",b); if(c>a && c>b){ printf("%d\n",c); }}return 0;} で、コンパイルはできたんですが、実行できません。3つの数値を入力してもその一番大きい数が出てきません。ifの条件は間違ってはいないと思うんですがやはり、最大が2つあるときのことを考えないとできませんか?

  • 四則演算のプログラム

    自力で解きたかったのですが、二時間考えても、とけないので 投稿させていただきます。どこを直せばよいのでしょうか 実行するときは%プログラム名 + 5 12 と入力して実行したいです。加えて参照にしている部分の %の扱いについても教えていただけると幸いです。 #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]){ char kigou; double num1,num2; kigou=atof(argv[1]); num1=atof(argv[2]); num2=atof(argv[3]); if(kigou=='+'){ printf("%f+%f=%f\n",num1,num2,num1+num2); } else if(kigou=='-'){ printf("%f-%f=%f\n",num1,num2,num1-num2); } else if(kigou=='x'){ printf("%f*%f=%f\n",num1,num2,num1*num2); } else if(kigou=='/'){ printf("%f/%f=%f\n",num1,num2,num1/num2); } /* else if(kigou=='%'){ printf("%f%%f=%f\n",num1,num2,num1%num2); }*/ else{ printf("Please input +,-,x,%%.\n");} }

  • Cのプログラム(初心者)

    #include<stdio.h> void main(void) { int a,b,c; printf("西暦で生まれた年を入力してください。\n"); scanf("%d",&a); printf("今の年を西暦で入力してください。\n"); scanf("%d",&b); c=b-a; if('0'<=c&&c<='23'){ printf("あなたは%d歳です。げんき。\n",c); } else if('24'<=c&&c<='40'){ printf("あなたは%d歳です。仕事盛り。\n",c); } else if('41'<=c&&c<='60'){ printf("あなたは%d歳です。まだいける。\n",c); } else if('61'<=c&&c<='99'){ printf("あなたは%d歳です。がんばれ。\n",c); } else{ printf("100歳以上なの?\n"); } } というプログラムを作っているのですが、うまく実行できません。間違いがあると思うのですが、それもよくわかりません。ビルドは成功するのですが、どの数字を入力しても「げんき」しか出てきません。 わかる人がいたら教えてください。 お願いします。

  • 条件演算子論理ORについて

    すみません、独学でC言語を学んでいるものです。 どうかお助けいただけませんか? テキストに載っているものをそのままコンパイラしているのに エラーがでました。どこがいけないのか確認していただけませんか? *Memopad.cppで作ったプログラム* #include<stdio.h> void main(void) { int a,b,c; a=0; b=0; c=0; if((a=1)||(b=2)||(c=3)) { printf("%d\n",a); printf("%d\n",b); printf("%d\n",c); } } *エラーメッセージ* 添付を参照下さい。 うまくいくと 1 0 0 と表示されるようです。ずっと考えてもわからなかったのでお力を貸して頂ければ助かります。 よろしくお願いします。

  • またプログラムの修正おねがいします。

    キーボードから出力した3つの整数について、以下の判定を行い 判定結果を出力するプログラムを作成する。 全部同じ 2つ同じ バラバラ * 論理演算子を使わないこと。 * インデントを正しくつけること。 #include<stdio.h> void main(void) { int a,b,c; printf("a --->"); scanf("%d",$a); printf("b --->"); scanf("%d",$b); printf("c --->"); scanf("%d",$c); if(a==b){ if(b==c){ printf("全部同じ\n"); } } else if(a!=b){ if(b==c){ printf("2つ同じ"); } else if(a==c){ printf("2つ同じ"); } else{ printf("バラバラ"); } } } 最近c言語を習ったばっかりなのでわからないとこだらけです。よろしくお願いします。