ユーザーとして、スタークは、コメントで、(これは思っていたよりもはるかに珍しく、私は思う)と指摘しています。または基数2で、より多くの数字で。そして、あなたは、基数10のために学校で学んだ長時間の除算アルゴリズムを使うことができます。
非常に大きな数字で除算を行うためのより良いアルゴリズムがありますが、あなたは非常に単純で非効率的、次の行(これはあなたが、もはやそうすることはできないまでちょうど分母の左シフトバージョンをオフ差し引いになるベース-2バージョン、である)に沿って:誤解を避けるため
// Treat x,y as 160-bit numbers, where [0] is least significant and
// [4] is most significant. Compute x mod y, and put the result in out.
void mod160(unsigned int out[5], const unsigned int x[5], const unsigned y[5]) {
unsigned int temp[5];
copy160(out, x);
copy160(temp, y);
int n=0;
// Find first 1-bit in quotient.
while (lessthanhalf160(temp, x)) { lshift160(temp); ++n; }
while (n>=0) {
if (!less160(out, temp)) sub160(out, temp); // quotient bit is 1
rshift160(temp); --n; // proceed to next bit of quotient
}
}
、上記は単なるスケッチである:
- バグがいっぱいあるかもしれません。
- 私は
less160
のようなビルディングブロック関数の実装を書いていません。
- 実際には、別々の機能を持つのではなく、インラインのコードを置くだけでしょう。たとえば、
copy160
は、わずか5つの割り当て、または短いループ、またはmemcpy
です。
確かに効率的にすることができます。一度に1つの場所をシフトするのではなく、先行する0ビットをカウントしてから1つのシフトを行う方がよい場合があります。 (右シフトはおそらくそれをやりたいとは思わないかもしれませんが、半分の時間シフトを行うためです)
"base-2^32"の方が速いかもしれませんが、実装は少し複雑になります。
実際には任意の数値を法としていますか、それとも常に0 ... 01 ... 1の形式のモジュロですか? –
@stark:pow(2,160)〜1e48。私は長いintそれをカバーできるとは思わない。 – tmh1999
...モジュラスは160ビット長か、それともいつも短くなりますか? –