• ベストアンサー

商と剰余を同時に求める(C言語)

C言語についてですが、 整数の除算を行うときに、商と剰余を同時に求めることは可能なは ずなので、1回の演算で両方知りたいのですが、c = a / b;だと商 だけ、d = a % b;だと剰余だけしか分からないです。 1回の演算で両方得たい場合はどう記述すればいいでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • KoHal
  • ベストアンサー率60% (110/181)
回答No.4

stdlib.hのdiv()ではダメなのですか? 商と余からなる構造体 div_tを返します。

matyrcry
質問者

お礼

ありがとうございました。 おかげで処理時間を短縮できました。

matyrcry
質問者

補足

ありがとうございます。 うちのstdlibにも同じ定義がありました。 さっそく試してみます。

その他の回答 (7)

  • mssine
  • ベストアンサー率24% (38/156)
回答No.8

>商と剰余を同時に求めることは可能なはずなので x86では可能ですが、それが出来ないプロセッサもあります。(TRONチップがそうだったような。。) Cは汎用言語なので、どんなプロセッサでも同じソースで動かなければならないので、こういう風になっているんだと思います。 x86環境ならインラインアセンブラで void div(int a, int b, int *c, int *d) { _asm { mov eax, a mov edx, 0 idiv b mov ebx, [c] mov ecx, [d] mov [ebx], eax mov [ecx], edx } } main() { int a,b,c,d; div(a, b, &c, &d); } #7様 除数と被除数の両方が定数で無い場合、最適化しても除算は2回になってしまうと思うのですが。。 除数が2,4,8..なら除算しないでシフトするだけかと思われます。

matyrcry
質問者

お礼

ありがとうございました。

  • yasuch
  • ベストアンサー率41% (27/65)
回答No.7

下記のコードをMSVC 6.0でコンパイルしてみたんですが アセンブラ出力で確認したところ、 最適化無し(/Od)では除算は2回 速度最適化(/O2)では除算は1回 でしたの。 自分のコンパイラでも確認して、あとはコンパイラの最適化に 任せてはいかがでしょうか。 int r = (int)rand(); int quot = r/3; int rem = r%3; printf("%d, %d\n", quot, rem);

matyrcry
質問者

お礼

ありがとうございました。

  • qKAZp
  • ベストアンサー率47% (71/148)
回答No.6

C++Builderの実装を見たんですが、div()はアセンブラで実装されてますね。 速そう。

matyrcry
質問者

お礼

ありがとうございました。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.5

1回の演算でできないのは、他の方々が言われているとおりです。 どうしても、1回でやりたい場合は、#3のかたのように関数を自作することになりますが、この程度の関数なら、マクロで実装することもできます。 ------------------------------ //商と余りを同時に求める #include <stdio.h> #define MYDIV(HIJOSU,JOSU,SHO,AMARI)\ {\ SHO = HIJOSU / JOSU;\ AMARI = HIJOSU % JOSU;\ } void main(void){ int sho1; int sho2; int amari1; int amari2; MYDIV(10,4,sho1,amari1) MYDIV(10,-3,sho2,amari2) printf("商=%d 余り=%d\n",sho1,amari1); printf("商=%d 余り=%d\n",sho2,amari2); } ------------------------------- MYDIVのパラメータは被除数、除数、商、余りになっています。 被除数、除数を与えると商、余りが求められます。 商と余りを同時に必要とする演算が、ソースの中に大量に存在する場合は、このようなマクロを使用すると視認性は良くなります。 通常は、2回の演算を行う方法で十分かと思いますが・・・。

matyrcry
質問者

お礼

ありがとうございました。

  • ysk6406
  • ベストアンサー率40% (237/589)
回答No.3

C の式は、一度に2つの変数に値を代入するのは不可能です。(Perl ならできますが…) なので、どうしても商と剰余を同時に求めたいなら、次のような構造体を用意して、この構造体形式で値を返す(また、参照渡しでもいいのですが)関数でも書くしかないのではないでしょうか? struct warizan {   int   sho;   int   amari; }; struct warizan x; struct warizan div(int a, int b) {   static struct warizan  res;   res.sho = a / b;   res.amari = a % b;   return (res); } main() {   x = div(10, 3); }

matyrcry
質問者

お礼

ありがとうございました。

matyrcry
質問者

補足

説明不足で申し訳ありません。 時間短縮のために除算関数が2回呼ばれて演算時間 が浪費されているのをどうにかできないかなという のが今抱えている本題です。

  • tttt23
  • ベストアンサー率25% (76/303)
回答No.2

残念ながら C でそのような書き方はできません。 機械語で書けば 1 回でできるのに C ではずいぶん無駄なことをしないといけないと私も思います。 ただし、できのよいコンパイラであれば 1 回だけ除算をして結果の商と剰余を c と d に格納するような機械語に落としてくれます。

matyrcry
質問者

お礼

ありがとうございました。

  • yasuch
  • ベストアンサー率41% (27/65)
回答No.1

アセンブラなら可能ですが、Cなどの高級言語では左辺は一つしか取れないので、 1回の演算で商と剰余を同時に両方求めるというのは、不可能だと思います。

matyrcry
質問者

お礼

ありがとうございました。

関連するQ&A

  • C言語の課題で困っています。その1.四則演算

    二つの整数値を読み込んで、前者を後者で割り、その結果の商と余りを表示するプログラムを作成。 実行例にあるよう、ゼロで割るような場合への対処も考慮する。 実行例1: 整数の除算を行います。整数を入力してください。 整数A:13 整数B:5 13 ÷ 5 = 2 あまり 3 実行例2: 整数の除算を行います。整数を入力してください。 整数A:10 整数B:0 0でわることはできません! (注)プログラム実行時にキーボードからどんな整数を入力してもいいように作成すること。 という課題に取り組んでいますが、途中までしか記述できません。 どなたか助けてください。 下記が途中までの記述です。 /*二つの整数値を読み込んで、前者を後者で割り、その結果の商と余りを表示*/ #include <stdio.h> int main(void) { int na, nb; printf("shimasaki kazunori \n"); puts("整数の除算を行います。整数を入力してください。: \n"); printf("整数A:"); scanf("%d", &na); printf("整数B:"); scanf("%d", &nb); printf("na ÷ nb = %d あまり %d \n", na / nb, nb, na % nb); return(0); }

  • c言語のプログラムについて

    今年からC言語を始めた大学1年生です。レポートで四則計算を行うプログラムを6/19までに作らないといけないです。使えるのは今までに習った選択型、反復型、関数scanfです。このプログラムの留意点は次の4つです。 1.使う演算を選択してもらう   例えば   どんな演算をしますか? 1:+,2:-,3:*,4:/ (選択) 2.演算を行う数値を入力してもらう   例えば   a + b の計算をします。aを入力してください。 3.演算結果を表示する   ○+○の答えは ○です 4.計算終了か、それともほかの演算を行うか 決める   0:計算終了 1:他の計算を行う を選択してください  以下のプログラムはこのことを留意してプログラムをつくりました。どこがおかしいのでしょうか。 #include<stdio.h> main() { short a,b,m,n; long c,d,e,f; c = a + b; d = a - b; e = a * b; f = a / b; m = 1; printf("整数を入力してください:"); scanf("%d",&a); printf("どんな演算をしますか?:"); printf("1: +,2: -,3: ×,4: ÷ :"); scanf("%d",&n); while(m=1){ if(n<=4){ while(m=1){ switch (n<=4){ case 1: printf("整数を入力してください:"); scanf("%d",&b); printf("%d + %d = %d \n",a,b,c); break; case 2: printf("整数を入力してください:"); scanf("%d",&b); printf("%d - %d = %d \n",a,b,d); break; case 3: printf("整数を入力してください:"); scanf("%d",&b); printf("%d × %d = %d \n",a,b,e); break; case 4: printf("整数を入力してください:"); scanf("%d",&b); printf("%d ÷ %d = %d \n",a,b,f); break; } } } else { printf("計算できません。"); printf("演算をやり直してください。\n:"); } } printf("計算を終了しますか、それとも他の計算を行いますか?:"); printf("0:計算終了,1:他の計算を行う:"); scanf("%d",&m); printf("計算を終了します。\n"); } 提出期限があるのでなるべく早めのご回答待ってます。生意気言ってすいません。

  • c言語のプログラムです

    2つの生の整数の割り算a÷bはaからbを繰り返し引いていき、引くことが出来なくなるまでの回数を商、その時の残りを剰余をすることで、引き算だけを用いて実現することができる。このことを考慮して、while文と引き算だけを用いて割り算を実現しなさい。という問題なんですけどどのようにプログラムを作っていいやらわかりません 一様ヒントはあります ・変数としては、入力する二つの整数に対応する変数m,n、商に対応する変数q、剰余に対応する変数rを使うとよいでしょう。すべて整数ですのでintで宣言する。 皆さんのご協力お願いします

  • 剰余類の問題

    剰余類の問題について解説がなく自分の考え方が正しいのか判断できず困っています。 問題は 3の剰余類をC0,C1,C2とするとき 1. a ∈ C0 , b ∈ C1 のとき a + b はどれに属するか。 2. a ∈ C1 , b ∈ C2 のとき a + b はどれに属するか。 です。 以下自分の解答↓ C0 は整数を 3 で割った時、あまりが 0 になる整数の集合 C1 は整数を 3 で割った時、あまりが 1 になる整数の集合 C2 は整数を 3 で割った時、あまりが 2 になる整数の集合 なので、n を整数とすると、 C0 = { 3n } C1 = { 3n + 1 } C2 = { 3n + 2 } となる。 よって 1のときは a = 3n , b = 3n + 1 とし a + b = (3n) + (3n + 1) = 6n + 1 = 3(2n) + 1 nは整数なので2nも整数である。よってa + b ∈ C1 2のときは a = 3n + 1 , b = 3n + 2 とし a + b = (3n + 1) + (3n + 2) = 6n + 3 = 3(2n + 1) nは整数なので2n + 1も整数である。よってa + b ∈ C0 1 , 2 ともにC1 , C0 に属しているということは正しいのですが、解答にいたるまでの自分の考え方があっているかどうかがわかりません。(特に剰余類について) どなたかご教授よろしく御願いいたします。

  • C++で、b[bit]の非負整数(例えば、unsigned long)

    C++で、b[bit]の非負整数(例えば、unsigned long)2つa0,a1を用いて、2b[bit]の非負整数を表現した場合の除算に関する質問です。 非負整数 a=a0*2^b+a0 を b[bit]の非負整数 D(≠0) で割った、商と余りを求めたいのですが、例えば次のように求めようとします、 d0 = a0/D. m0 = a0%D. d1 = (m0*2^b+a1)/D = (m0*2^b)/D + a1/D m1 = (m0*2^b+a1)%D = (m0*2^b)%D + a1%D ですが、ここで (m0*2^b)/D と (m0*2^b)%D をb[bit]の非負整数に対する演算のみ(ループ処理も含めたくない)を用いて計算する方法が思いつかないのですが、何か良い方法はありませんでしょうか? 上記が計算できれば、 商 d = d0*2^b + d1. 余り m = m1 と構成できます。

  • 算術演算子にて、整数での除算処理は商になる?

    JAVAのプログラミングを勉強しているのですが、JAVAの算術演算子にて、 参考書に「除算演算子は割り算を行うものだが、整数同士の割り算を用いると「商」を計算する」と書かれているのですが、これはどういう意味でしょうか? 整数同士の割り算をすると、小数点ではなく四捨五入をした整数値が出力されるのでしょうか?

    • ベストアンサー
    • Java
  • c言語について

    C言語で、二つの整数値を読み込んで、前者の値が後者の何%であるかを実数で表示するプログラムを作成しようとして以下のコードを書きました。 #include <stdio.h> int main(void) { int n1, n2 ; puts("二つの整数を入力してください。") ; printf("整数A : \n") ; scanf("%d" , &n1) ; printf("整数B : \n") ; scanf("%d" , &n2) ; printf("Aの値はBの%f%%です。\n" , (double)(n1 / n2) * 100) ; return 0 ; } 上記コードを実行すると、0.000000%のような結果になります。 そこで、最後のキャスト演算子を使用した後の式で(n1 / n2) * 100がまずいのかなと考え、n1 / n2 * 100にしたら上手くいきました。 なぜ、上記コードだと上手くいかないんでしょうか?

  • C言語プログラム能力検定の問題でわからないところがあります

    今度C言語プログラム能力検定を受けるのですが、過去問の回答ではわからず質問させてもらってます(以下ソース) ------------------------------------------ #include<stdio.h> int mod(int a, int b); int d, f = 10; main() { int a,b,c; enum cl {g,h} a=12; b=5; c=mod(a,b); a++; ++b; c=mod(a,b); printf("c=%d\n",c); ←(1) } int mod(int b, int a) { int c; c=b/a; c=b-c*a; return(c); } -------------------------------------------------- 問題は(1)はどのように出力されるでしょう?といったもので、 答え(出力結果)は「1」でした。回答の説明によると 「変数cはmain関数内で宣言され、mod関数の戻り値が格納される。 mod関数の戻り値は二つの引数の剰余であり、ここでは2回目のmod関数 の戻り値が表示される。2回目の仮引数は、aが6で、bが13で戻り値は1になる」 ということでしたが>mod関数の戻り値は二つの引数の剰余であり… というのがよくわかりません…剰余算というのは「%」のことですよね? であれば「c= a % b」といった記述がでてくれば13÷6=2…1で「1」となり、理解できるのですが、それらしき記述がないので(--;) どなたか教えていただけないでしょうか? よろしくおねがいします。

  • c言語なのですが

    c言語なのですが #include<stdio.h> main() { int a; printf("整数を5回足し算する\n"); scanf("%d %d",&a); printf("a*5=%d\n",a*5); return(0); } でエラーが起こります どこを修正すればいいのでしょうか

  • c言語のプログラムで

    c言語で 2つの整数を読み込んで小さいほうの数以上で大きいほうの数以下の整数をすべて加えた値を表示するプログラム で最後の表示の仕方がわかりません。 実行結果は 整数1:37 整数2:28 28以上37以下の全整数は325です。と表示されるはずです。 この表示の3行目の28と37の表示がどうやればよいのかわかりません。 #include <stdio.h> int main(void) { int a, b; int sum=0; printf("整数1:"); scanf("%d",&a); printf("整数2:"); scanf("%d",&b); if(a>b) do{ sum=sum+b; b=b+1; }while(b<=a); else do{ sum=sum+a; a=a+1; }while(a<=b); printf("%d以上%d以下の全整数の和は%dです。",a,b,sum); return(0); } 全整数の表示はできます。 do文の中でa=cとかにしてやってみましたが、うまくいきませんでした。 お願いします。

専門家に質問してみよう