ユーザースタークがコメントで指摘しているように(必要以上に無礼だと思います)、これは基数2 ^ 32の長除算です。または、基数 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 つのシフトを行う方がよい場合があります。(しかし、右シフトはおそらくそれをしたくありません。なぜなら、半分の時間は 1 つのシフトだけを行うからです。)
「base-2^32」バージョンの方が高速かもしれませんが、実装はもう少し複雑になります。