• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C++で、b[bit]の非負整数(例えば、unsigned long))

C++でb[bit]の非負整数の除算に関する質問

このQ&Aのポイント
  • C++で、b[bit]の非負整数を表現した場合の除算に関する質問です。
  • 非負整数aをb[bit]の非負整数Dで割った商と余りを求める方法についての質問です。
  • C++で計算する際にループ処理を含まないで、(m0*2^b)/Dと(m0*2^b)%Dを求める方法が知りたいです。

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

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.1

まず、質問者さんの立てた式には、計算過程に誤りがあります。 d1 = (m0*2^b)/D + a1/D m1 = (m0*2^b)%D + a1%D この「/」が整数除算だとすると、この/・%では、正しい計算はできません。 (例えば、b=4bitで考えましょう。50=4*2^4+2ですが、これを7で割った場合、 (4*2^4)/7+2/7=48/7+2/7=6+0=6 (4*2^4)%7+2%7=48%7+2%7=6+2=8 つまり、50を7で割った商が6で余り8になってしまいます。 つまり、個別に出した商や余りを単純に足すことはできません。 さて、まず a0をDで割った商をa0d、余りをa0m a1をDで割った商をa1d、余りをa1m 2^bをDで割った商をbd、余りをbm (a0*2^b+a1)をDで割った商を(d0*2^d+d1)、余りをm とします。 このとき、元の数 a0、a1、2^bは、 a0 = a0d * D + a0m a1 = a1d * D + a1m 2^b= bd * D + bm という式が成り立ちますから、被除数 a0*2^b+a1 は、 (a0*2^b+a1) = (a0d * D + a0m)*2^b+(a1d * D + a1m) = (a0d*2^b+a1d)*D + (a0m*2^b+a1m) になります。ここで、右側の2^bに2^b= bd * D + bmを代入すると、 = (a0d*2^b+a1d)*D + (a0m*(bd*D+bm)+a1m) = (a0d*2^b+a1d+a0m*bd)*D + (a0m*bm+a1m) になります。 余りについては、 (a0d*2^b+a1d+a0m*bd)*D はDで割って余り0ですから、 m=(a0*2^b+a1)%D = (a0m*bm+a1m) % D として求めることができます。 商については、 (a0*2^b+a1)/D = ((a0d*2^b+a1d+a0m*bd)*D + (a0m*bm+a1m))/D = (a0d*2^b+a1d+a0m*bd)*D/D + (a0m*bm+a1m)/D = (a0d*2^b+a1d+a0m*bd) + (a0m*bm+a1m)/D になります。 つまり、基本としては、 d0=a0d d1=a1d+a0m*bd+(a0m*bm+a1m)/D a=(a0m*bm+a1m)%D になります。 (ただし、この計算において、d1がb[bit]からオーバーフローする場合もありえます。 その場合をきちんと検査して、d1から適切な値を引いて適宜d0の方を足す、などとといった処理が必要です また、a0m*bmがb[bit]からオーバーフローする場合もありえますので、そちらの検査も必要。 なお、 > 2^bをDで割った商をbd、余りをbm については、そのままではb[bit]の演算では表現できませんが、 2^(b-1)をDで割った商をbd'、余りをbm' とすると、 2^b=2^(b-1)*2 = (bd'*D+bm')*2 = 2*bd'*D+2*bm' になりますから、 bd=2*bd'+(2*bm')/D bm=(2*bm')%D として、b[bit]の演算で求められます。

mi65536
質問者

お礼

理解できました。丁寧に回答していただき、ありがとうございます。

関連するQ&A