除算アルゴリズムとは、2つの整数NとD(それぞれ分子と分母)が与えられたときに、それらの商および/または余り、つまりユークリッド除算の結果を計算するアルゴリズムのことである。手計算で用いられるものもあれば、デジタル回路設計やソフトウェアで使用されるものもある。
除算アルゴリズムは、大きく分けて低速除算と高速除算の2種類に分類されます。低速除算アルゴリズムは、反復ごとに最終商の1桁を生成します。低速除算の例としては、復元除算、非復元除算、非復元除算、SRT除算などがあります。高速除算法は、最終商の近似値から開始し、反復ごとに最終商の2倍の桁数を生成します。[ 1 ]ニュートン・ラフソン法とゴールドシュミット法はこのカテゴリに属します。
これらのアルゴリズムの変種を用いることで、高速な乗算アルゴリズムを利用できるようになる。その結果、大きな整数については、どの乗算アルゴリズムを用いても、除算に必要なコンピュータ時間は、定数倍を除いて、乗算に必要な時間と同じになる。
議論はフォームを参照します、 どこ
は入力であり、
これが出力です。
最も単純な除算アルゴリズムは、歴史的にユークリッドの『原論』第7巻命題1に示されている最大公約数アルゴリズムに組み込まれており、減算と比較のみを用いて2つの正の整数の余りを求めます。
function divide_unsigned ( N , D ) if D = 0 then error ( DivisionByZero ) end R : = N Q : = 0 while R ≥ D do R : = R − D Q : = Q + 1 end return ( Q , R ) end商と余りが存在し、かつ一意であることの証明(ユークリッド除法で説明されている)は、加算、減算、比較を用いて、負の数と正の数の両方に適用できる完全な除算アルゴリズムを生み出す。
function divide ( N , D ) if D = 0 then error ( DivisionByZero ) end if D < 0 then ( Q , R ) : = divide ( N , − D ) return ( − Q , R ) end if N < 0 then ( Q , R ) : = divide ( − N , D ) if R = 0 then return ( − Q , 0 ) else -- 例: N = -7、D = 3 -- divide(-N, D) = divide(7, 3) = (2, 1) -- R ≠ 0 なので return (-2 - 1, 3 - 1) = (-3, 2) -- チェック: (-3)*3 + 2 = -7 return ( − Q − 1 , D − R ) end end -- この時点で、N ≥ 0 かつ D > 0 return divide_unsigned ( N , D ) endこの手順は常に R ≥ 0 を生成します。非常に単純ですが、 Ω (Q) ステップかかるため、長除法のような遅い除算アルゴリズムよりも指数関数的に遅くなります。Q が小さいことがわかっている場合(出力に敏感なアルゴリズムであるため)、この手順は有用であり、実行可能な仕様として使用できます。
別の実装方法としては、剰余をインクリメントし、除数に達したらそれをリセットする方法がある。
のためにアルゴリズムは計算しますそのため、 と:
Pythonの以下のコードを考えてみてください。
def divide_unsigned2 ( numerator : int , denominator : int ) -> tuple [ int , int ] quotient : int = 0 remainder : int = 0 for _ in range ( numerator ): remainder += 1 if remainder == denominator : quotient += 1 remainder = 0 return quotient , remainder注記
quotient代入がコードから削除され、出力リストから削除されても、divide_unsigned2 はdivide_unsigned と同様に計算されます。quotient。カウンタマシンとしての代替実装 シンプルなカウンタマシン(CM)は、代替実装に基づいて構築できます。CMの命令は[ 3 ] [ 4 ]です。
カウンタマシンプログラムは[ 5 ]です。
1: J(1,5,0) 2: S(4) 3: J(4,2,6) 4: S(5) 5: J(0,0,1) 6: S(3) 7: Z(4) 8: S(5) 9: J(0,0,1) CM が初期レジスタ値 R1=N、R2=D (残りのレジスタ = 0) での計算を完了した後、
筆算は、十進数で表された多桁の数を紙とペンで割り算する際に用いられる標準的なアルゴリズムです。被除数の左端から右端へと徐々に計算を進め、各段階で除数の最大の倍数(桁レベルで)を引いていきます。引いた倍数が商の桁となり、最終的な差が余りとなります。
2進数基数で使用する場合、この方法は、後述の(符号なし)整数除算と剰余アルゴリズムの基礎となります。短除法は、1桁の除数に適した長除法の簡略化された形式です。チャンキング(部分商法またはハングマン法とも呼ばれる)は、長除法の効率は劣りますが、理解しやすい形式です。各段階で現在持っている倍数よりも多くの倍数を減算できるようにすることで、長除法のより自由な形式も開発できます。
以下のアルゴリズムは、有名な筆算の二進数版であり、 NをDで割り、商をQに、余りをRに格納します。以下の擬似コードでは、すべての値は符号なし整数として扱われます。
if D = 0 then error ( DivisionByZeroException ) end Q : = 0 -- 商と剰余をゼロに初期化R : = 0 for i : = n − 1 .. 0 do -- ここで n は N のビット数R : = R << 1 -- R を 1 ビット左シフトR ( 0 ) : = N ( i ) -- R の最下位ビットを分子の i ビットに等しく設定if R ≥ D then R : = R − D Q ( i ) : = 1 end endN=1100 2 (12 10 ) および D=100 2 (4 10 )とすると
ステップ1:R=0、Q=0と設定する。 ステップ2:i=3とする(Nのビット数より1少ない)。 ステップ3:R=00とする(1ビット左シフト)。 ステップ4:R=01とする(R(0)をN(i)に設定する)。 ステップ5:R < Dなので、この文をスキップする。
ステップ2:i=2に設定 ステップ3:R=010 ステップ4:R=011 ステップ5:R < D、ステートメントはスキップ
ステップ2:i=1に設定 ステップ3:R=0110 ステップ4:R=0110 ステップ5:R>=D、ステートメントが入力 ステップ5b:R=10(R−D) ステップ5c:Q=10(Q(i)を1に設定)
ステップ2:i=0に設定 ステップ3:R=100 ステップ4:R=100 ステップ5:R>=D、ステートメントが入力 ステップ5b:R=0(R−D) ステップ5c:Q=11(Q(i)を1に設定)
終了 Q=11 2 (3 10 ) および R=0。
遅い除算法はすべて標準的な漸化式に基づいています[ 6 ]
どこ:
復元除算は固定小数点数に対して実行され、0 < D < Nという仮定に依存します。
商の数字qは、数字の集合{0,1}から構成される。
2進数(基数2)復元除算の基本アルゴリズムは次のとおりです。
R : = N D : = D << n -- R と D は N と Q の 2 倍のワード幅が必要ですfor i : = n − 1 .. 0 do -- 例えば 32 ビットの場合は 31..0 R : = 2 * R − D -- シフトされた値からの試行減算 (2 倍はバイナリ表現でのシフトです) if R >= 0 then q ( i ) : = 1 -- 結果ビット 1 else q ( i ) : = 0 -- 結果ビット 0 R : = R + D -- 新しい部分剰余は (復元された) シフトされた値ですend end-- ここで、N = 分子、D = 分母、n = ビット数、R = 部分剰余、q(i) = 商のビット番号i非実行復元除算は、2R の値が保存される点を除いて復元除算と似ています。そのため、 R < 0の場合、D を再度加算する必要はありません。
非復元除算では、商の桁として{0, 1}ではなく{-1, 1}の桁セットを使用します。このアルゴリズムはより複雑ですが、ハードウェアで実装する場合、商ビットごとに1回の判定と加算/減算のみで済むという利点があります。減算後に復元ステップがないため[ 7 ] 、演算回数を最大で半分に減らすことができ、より高速に実行できます[ 8 ] 。 非負数のバイナリ(基数2)非復元除算の基本アルゴリズムは次のとおりです。
-- 入力: N (分子)、D (分母) -- n = ビット数-- R と D は通常、シフトを処理するために幅 2n またはそれに近いレジスタに格納されますR : = N -- 剰余を初期化するfor i = n − 1 .. 0 do -- 例えば 31..0 で 32 ビットの場合-- 剰余を左にシフト (代数的に: 2 * R) if R >= 0 then R : = 2 * R - D ; -- D を減算q ( i ) : = 1 ; -- 商のビットを 1 として記録else R : = 2 * R + D ; -- D を加算 (復元) q ( i ) : = - 1 ; -- 商のビットを -1 として記録end if end forこのアルゴリズムに従うと、商は−1と+1の数字で構成される非標準形式になります。この形式をバイナリに変換して最終的な商を作成する必要があります。例:
−1 桁が一般的なようにゼロ(0)として保存され、はコンピューティング自明です。元のデータに対して1の補数(ビットごとの補数)を実行します。。
Q : = Q − bit . bnot ( Q ) -- Q の −1 桁が一般的なようにゼロとして表現される場合に適切です。最後に、このアルゴリズムで計算される商は常に奇数であり、剰余Rは−D ≤ R < Dの範囲になります。例えば、5 / 2 = 3 R −1です。正の剰余に変換するには、 Qを非標準形式から標準形式に変換した後、復元ステップを1回実行します。
R < 0の場合、Q : = Q − 1、R : = R + D -- 余りが関心のある場合にのみ必要。end if実際の剰余は R >> n です。(除算の復元と同様に、R の下位ビットは商 Q のビットが生成されるのと同じ速度で消費され、両方に単一のシフトレジスタを使用するのが一般的です。)
SRT 除算は、多くのマイクロプロセッサ実装でよく使われる除算方法です。[ 9 ] [ 10 ]このアルゴリズムは、 IBMの DW Sweeney、イリノイ大学の James E. Robertson 、インペリアル カレッジ ロンドンのKD Tocherにちなんで名付けられました。彼らは全員、ほぼ同時期に独立してこのアルゴリズムを開発しました (それぞれ 1957 年 2 月、1958 年 9 月、1958 年 1 月に発表)。[ 11 ] [ 12 ] [ 13 ]
SRT除算は非復元除算に似ていますが、被除数と除数に基づいたルックアップテーブルを使用して、商の各桁を決定します。
最も大きな違いは、商に冗長な表現が用いられる点です。例えば、基数4のSRT除算を実装する場合、各商の桁は、 −2、−1、0、+1、+2の5つの選択肢から選ばれます。このため、商の桁の選択は必ずしも完璧である必要はなく、後の桁でわずかな誤差を補正できます。(例えば、0 × 4 + 2 = 1 × 4 − 2 なので、商の桁のペア(0, +2)と(1, −2)は等価です。)この許容範囲により、全幅減算を行う必要がなく、被除数と除数の最上位ビット数ビットのみを使用して商の桁を選択できます。この簡略化により、2より大きい基数を使用できるようになります。
非復元除算と同様に、最終ステップは、最後の商ビットを解決するための最終的な全幅減算と、商を標準バイナリ形式に変換することです。
初代Intel Pentiumプロセッサの悪名高い浮動小数点除算バグは、ルックアップテーブルのコーディングミスが原因でした。Pentium プロセッサは 2048 セルのテーブルを使用しており、そのうち 1066 セルに値が格納されるはずでしたが、5 つのセルの値が誤って省略されていました。[ 14 ] [ 15 ] [ 16 ]
ニュートン・ラフソン法はニュートン法を用いて逆数を求める。そしてその逆数を掛ける最終的な商を求める。
ニュートン・ラフソン法の手順は以下のとおりです。
ニュートン法を適用して逆数を求めるには関数を見つける必要があるゼロを持つ明らかなそのような関数はしかし、このためのニュートン・ラフソン反復法は役に立たない。なぜなら、逆数を既に知っていなければ計算できないからである。(さらに、反復的な改善を可能にするのではなく、1ステップで正確な逆数を計算しようとします)。実際に機能する関数は次のとおりです。、ニュートン・ラフソン反復法では次のようになる。
これは以下から計算できます乗算と減算のみを使用するか、2 つの融合乗算加算を使用します。
計算の観点から、式そしてこれらは等価ではありません。2 番目の式を使用して 2 nビットの精度で結果を得るには、次の積を計算する必要があります。そして与えられた精度の2倍で(nビット)。対照的に、そしてnビットの精度で計算するだけでよい。なぜなら、ゼロです。
エラーが次のように定義される場合、 それから:
各反復ステップで誤差を二乗するこの方法(ニュートン・ラフソン法のいわゆる二次収束)は、結果の正しい桁数が反復ごとにほぼ倍増するという効果をもたらします。これは、対象となる数値の桁数が多い場合(例えば、大きな整数領域)に非常に有用な特性となります。しかし、これはまた、特に初期推定値が小さい場合、この方法の初期収束が比較的遅くなる可能性があることを意味します。 選択が適切ではない。
初期推定値の選択という部分問題について除数Dにビットシフトを適用して0.5 ≤ D ≤ 1となるようにスケーリングすると便利です。分子Nにも同じビットシフトを適用することで、商が変化しないことが保証されます。範囲が限定されたら、単純な多項式近似を使用して初期推定値を求めることができます。
区間における最小最悪ケース絶対誤差の線形近似は:
線形近似の係数は次のように決定されます。誤差の絶対値は誤差の最大絶対値の最小値は、チェビシェフの等振動定理を適用して決定されます。局所最小値発生するのは解決策があるその最小値における関数は、端点における関数とは逆の符号でなければならない。すなわち、2つの未知数を含む2つの方程式は、一意の解を持つ。そして最大誤差はこの近似を用いると、初期値の誤差の絶対値は以下より小さくなる。
最適な二次近似区間は
これは、誤差を再スケーリングした第1種3次チェビシェフ多項式に等しくするように選択され、誤差の絶対値は1/99以下になります。この改善は、ニュートン・ラフソン法による反復計算は、1回の反復計算よりも少ない計算コストで済みます。
レメズアルゴリズムを用いて係数を計算することで、2次以上の多項式近似を生成することが可能です。ただし、初期推定にはより多くの計算サイクルが必要となりますが、その代わりにニュートン・ラフソン法の反復回数を減らすことが期待できます。
この方法では収束が正確に二次関数であるため、初期誤差から次のことが導かれる。、反復により、正確な答えが得られます。
バイナリの桁数。典型的な値は次のとおりです。
IEEE単精度では、2次式の初期推定値と2回の反復計算で十分な精度が得られますが、倍精度では3回の反復計算では限界があります。倍精度と倍精度拡張の両方の形式では、線形式の初期推定値と4回の反復計算で十分です。
以下は、 NとDの商をP桁の精度で計算するものです。
D を M × 2 eで表す(1 ≤ M < 2、標準浮動小数点表現) D' := D / 2 e+1 // 0.5 から 1 の範囲にスケーリング。ビットシフト / 指数減算で実行可能 N' := N / 2 e+1 X := 48/17 − 32/17 × D' // D と同じ精度で定数を事前計算するrepeat回数// 固定Pに基づいて事前に計算可能 X := X + X × (1 - D' × X) end return N' × X
例えば、倍精度浮動小数点除算の場合、この方法では10回の乗算、9回の加算、2回のシフト演算が必要になります。
誤差を3乗するために3回の乗算を用いる反復処理があります。
Y i ε iという項は新しいものです。
上記をさらに展開すると、次のように書くことができます
その結果、誤差項は
これは二次反復の計算の3/2ですが、収束性は同程度であるため、わずかに効率的です。言い換えれば、この方法を2回繰り返すと、誤差は9乗に増加しますが、計算コストは同じで、2次反復を3回繰り返すと誤差は8乗にしか増加しません。
正しいビット数反復回数は
バイナリの桁数。典型的な値は次のとおりです。
2次初期推定値に2回の3次反復計算を加えることで、IEEE倍精度結果に必要な十分な精度が得られます。また、2次反復計算と3次反復計算を組み合わせることも可能です。
少なくとも1回の二次反復を使用することで、誤差が正になることが保証されます。つまり、逆数が過小評価されます。[ 17 ]: 370正確に丸められた商が必要な場合は、これにより後続の丸めステップが簡略化されます。
初期化または反復処理において高次の多項式を使用すると、余分な乗算が必要になるため、その時間をより多くの反復処理に費やす方が効率的であるため、パフォーマンスが低下します。
ゴールドシュミット除法[ 18 ](ロバート・エリオット・ゴールドシュミットによる)[ 19 ]は、除数が1に収束するように選択された共通因子F iで被除数と除数の両方を繰り返し乗算する反復プロセスを使用します。これにより、被除数は求める商Qに収束します。
ゴルトシュミット除法の手順は以下のとおりです。
N / D が 0 < D < 1となるようにスケーリングされていると仮定すると、各F i はDに基づいている。
被除数と除数を因数で掛け合わせると次のようになります。
十分な回数kの反復の後。
ゴールドシュミット法は、AMD Athlon CPU およびそれ以降のモデルで使用されています。[ 20 ] [ 21 ]また、アンダーソン・アール・ゴールドシュミットべき乗 (AEGP) アルゴリズムとしても知られており、さまざまなIBMプロセッサで実装されています。[ 22 ] [ 23 ]ニュートン・ラフソン法と同じ速度で収束しますが、ゴールドシュミット法の利点の 1 つは、分子と分母の乗算を並列に実行できることです。[ 23 ]
ゴールドシュミット法は、二項定理による簡略化を可能にする因子とともに使用できます。 と仮定します。は2のべき乗でスケーリングされ、私たちは選びますそしてこれにより、
nステップ後分母丸めることができます1相対誤差付き
これは最大でいつこれにより、最小限の精度が確保されます。二進数。
ハードウェア実装用に設計された方法は、一般的に、数千または数百万の十進数を持つ整数には対応できません。このような整数は、たとえば暗号化におけるモジュラー削減などで頻繁に発生します。このような大きな整数に対しては、より効率的な除算アルゴリズムによって、問題を少数の乗算を使用するように変換し、その後、カラツバアルゴリズム、トゥーム・クック乗算、またはシェーンハーゲ・シュトラッセンアルゴリズムなどの漸近的に効率的な乗算アルゴリズムを使用して実行できます。結果として、除算の計算複雑度は、乗算の計算複雑度と同じオーダーになります(乗法定数を除く)。例としては、上記で説明したニュートン法による乗算への還元[ 24 ]、およびわずかに高速なバーニケル・ジーグラー除算[ 25 ]、バレット削減、モンゴメリー削減アルゴリズムなどがあります。[ 26 ]ニュートン法は、同じ除数で何度も割る必要があるシナリオで特に効率的です。最初のニュートン逆変換の後、各除算には 1 つの (切り捨てられた) 乗算のみが必要だからです。
定数Dによる除算は、その逆数による乗算と同等です。分母は定数なので、その逆数 (1/ D ) も定数です。したがって、コンパイル時に(1/ D )の値を一度計算し、実行時に除算N/Dではなく乗算N ·(1/ D ) を実行することが可能です。浮動小数点演算では (1/ D )の使用はほとんど問題になりませんが、[ a ]整数演算では、逆数は常にゼロと評価されます (| D | > 1 の場合)。
(1/ D )を明示的に使用する必要はありません。( X / Y ) が (1/ D ) に還元される値であれば、どれでも使用できます。たとえば、3 で割る場合、1/3、2/6、3/9、または 194/582 を使用できます。したがって、Yが 2 のべき乗であれば、除算ステップは高速右ビットシフトに還元されます。N/D を (N·X)/Y として計算すると、除算が乗算とシフトに置き換えられます。括弧が重要であることに注意してください。N ·( X / Y )はゼロに評価されます。
しかし、D自体が 2 のべき乗でない限り、上記の条件を満たすXとYは存在しません。幸いなことに、( N · X )/ Y は、 ( X / Y ) が1 / Dと完全に等しくなくても、近似によって生じる誤差がシフト操作によって破棄されるビットにあるほど「十分近い」場合でも、整数演算では N / Dとまったく同じ結果を与えます。 [ 27 ] [ 28 ] [ 29 ]バレット縮約では、 Yの値に 2 のべき乗を使用して、 Yによる除算を単純な右シフトにします。[ b ]
具体的な固定小数点演算の例として、32 ビット符号なし整数の場合、3 による除算は 2863311531 / 2 33 による乗算に置き換えることができます。これは、2863311531 (16進数0xAAAAAAAB)による拡大乗算の後に 33 ビット右シフトを行うものです。2863311531 の値は 2 33 / 3 として計算され、切り上げられます。同様に、10 による除算は、3435973837 (0xCCCCCCCD) による乗算の後に 2 35 (または 35 ビット右シフト)による除算として表現できます。 [ 31 ] : p230-234 OEIS は、乗算の定数のシーケンスをA346495として、右シフトの定数のシーケンスをA346496として提供しています。
除数D が2 のべき乗でない一般的なxビット符号なし整数除算の場合、次の恒等式は除算を 2 つのxビット加算/減算、1 つのxビット× xビット乗算 (結果の上位半分のみを使用)、およびいくつかのシフトに変換します。そして:
場合によっては、「定数を掛ける」を一連のシフトと加算または減算に変換することで、定数による除算をさらに短時間で実行できます。[ 32 ]特に興味深いのは10による除算で、必要に応じて余りとともに正確な商が得られます。[ 33 ]
除算演算を実行すると、正確な商はそして残りコンピュータの精度限界内に収まるように近似されます。除算アルゴリズムは次のとおりです。
どこ。
浮動小数点演算では、商はは次のように表されます。そして残りはとして丸め誤差が生じるそして:
この丸め処理によって小さな誤差が生じ、それが後続の計算で伝播・蓄積される可能性があります。このような誤差は、反復処理やほぼ等しい値を減算する場合に特に顕著になります(有効数字の喪失と呼ばれます)。これらの誤差を軽減するために、ガード桁の使用やより高い精度(または任意精度)などの手法が用いられます。[ 34 ] [ 35 ]
denominator正でなければなりません。の無制限レジスタマシン(URM)シミュレータ(エミュレータ)は、「仮想URM」です。これは、ケンブリッジ大学出版局のナイジェル・J・カットランド著『計算可能性:再帰関数理論入門』に記載されているURM仕様に基づいて作成されています。
{{citation}}: CS1メンテナンス: 場所の発行元が見つかりません (リンク){{citation}}: CS1メンテナンス: 場所の発行元が見つかりません (リンク)