Modulo演算 を通過する( rem
とmod
の違いを調べているときに入力した道)私は出会いました:
数学では、剰余演算の結果はユークリッド除算の残りの部分です。ただし、他の規則も可能です。コンピュータと計算機には、数値を保存および表現するさまざまな方法があります。したがって、それらのモジュロ演算の定義は、プログラミング言語や基盤となるハードウェアに依存します。
質問:
最近のすべてのコンピュータのハードウェアは、パフォーマンスに影響を与えない(または些細な)影響を与えずにいずれかの符号のmod操作を実装するのに十分強力です。これは理由ではありません。
ほとんどのコンピューター言語の一般的な期待は、(a div b)* b +(a mod b)= aです。言い換えると、divとmodが一緒に考慮されると、数値をいくつかの部分に分割して、確実に元に戻すことができます。この要件は、C++標準では明示的です。この概念は、多次元配列のインデックス付けと密接に関連しています。よく使っています。
これから、bが正の場合(通常の場合)、divとmodはaの符号を保持することがわかります。
一部の言語は、modに関連する「rem()」関数を提供し、他のいくつかの数学的な正当化があります。私はこれを使用する必要がありませんでした。たとえば、Gnu Cのfrem()を参照してください。[編集]
通常、プログラミングにはX == (X/n)*n + X%n
が必要です。したがって、モジュロの定義方法は、整数除算の定義方法によって異なります。
これを念頭に置いて、「プログラミング言語の設計者が整数除算の動作を決定するときに使用される根拠は何ですか? "
実際には約7つの選択肢があります。
次に、-( (-X) / n) == X/n
について考えます。他のものは一貫性がないように見えますが(浮動小数点の場合は真実です)、非論理的です(バグの原因である可能性があり、最適化の失敗の可能性もあります)。このため、整数除算の最初の2つの選択肢(どちらかの無限大に丸める)は望ましくありません。
すべての「最も近い値に丸める」選択は、特にビットマップのようなことをしている場合(たとえば、offset = index / 8; bitNumber = index%8;
)。
これにより、「最も健全な可能性がある」選択肢としてゼロへの丸めが残ります。これは、moduloが分子(またはゼロ)と同じ符号の値を返すことを意味します。
注:ほとんどのCPU(私が認識しているすべてのCPU)も同じ「ゼロへの丸め」方法で整数除算を行うことにも注意してください。これは同じ理由である可能性があります。
まず、モジュロbはa-b *(a div b)と等しくなければならないことを繰り返します。言語がそれを提供しない場合、あなたはひどい数学的混乱に陥っています。その式a-b *(a div b)は、実際にはbを法としてaを計算する実装の数です。
いくつかの可能な根拠があります。 1つ目は、最大速度が必要なことです。そのため、div bは、使用するプロセッサが提供するものとして定義されます。プロセッサに「div」命令がある場合、div bはdiv命令が実行するものです(それがまったく正気ではない限り)。
2つ目は、特定の数学的な動作が必要なことです。最初にb> 0と仮定しましょう。divbの結果をゼロに丸めるのは非常に合理的です。したがって、4 div 5 = 0、9 div 5 = 1、-4 div 5 = -0 = 0、-9 div 5 = -1となります。これにより、(-a)div b =a div b)および(-a)modulo b =-(a modulo b)が得られます。
これは---(かなり妥当ですが、完璧ではありません。たとえば、(a + b)div b =(a div b)+ 1は、a = -1の場合、成り立たない。固定されたb> 0の場合、通常、(b)aには可能な値があり、div bが同じ結果を返しますが、-b + 1からb-1までの2b-1の値aがありますが、div bは0です。 。また、aが負の場合、bを法とする剰余も負になることを意味します。モジュロbは常に0からb-1までの範囲の数値である必要があります。
一方、aの連続する値を通過するときに、aを法とするaが0からb-1までの値を通過してから、再び0で始まるように要求することも非常に合理的です。また、(a + b)div bが(a div b)+ 1であることを要求するには、div bの結果を-無限大に丸める必要があるため、-1 div b = -1とします。繰り返しますが、欠点もあります。 (-a)div b =-(a div b)は成立しません。 2または任意の数b> 1で繰り返し除算しても、最終的に0の結果は得られません。
対立があるので、言語は彼らにとってどの利点のセットがより重要であるかを決定し、それに応じて決定しなければなりません。
負のbの場合、ほとんどの人は最初にa div bとaを法とするaがどうあるべきか頭をつかむことができないため、簡単な方法はdiv b =(-a)div(-b)とa modulo b =(-a)modulo(-b)if b <0、または正のbのコードを使用した自然な結果。