23

今日、職場で同僚の一人と興味深い話をしました。次のようなことが起こったとき、彼は驚いた。

assert(-1 % 10 == -1)  //Expecting 9

それで、彼が私にそれについて尋ねに来たとき、私は彼に言いました。 「常に正の」モデル. 私は少し調査を行い、彼が言及していたモジュラスが次のように見えることを発見しました:

q を a と n の整数商とします。r を剰余とします。それで:

a = n * q + r

ただし、私が使用していた定義は、係数のクヌース版のようです。つまり、次のとおりです。

q を n で割った a の床とする。r を剰余とします。それで:

r = a - n * q

それで、私の質問は、モジュラス演算子を0に向かって切り捨てることがFORTRAN標準(およびその後のC標準)で終わったのはなぜですか? それを「剰余」ではなく「モジュラス」と呼ぶのは、私には誤解のように思えます (数学では、答えは実際には 9 になるはずです)。これは、ハードウェアが分割を行う方法に関連していますか?

参考のため:

TLDR; モジュラス演算子が 0 に向かって切り捨てられる理由はハードウェアですか?

4

3 に答える 3

16

それを「剰余」ではなく「モジュラス」と呼ぶのは、私には誤解のように思えます (数学では、答えは実際には 9 になるはずです)。

C はこれを % 演算子と呼び、その結果を余りと呼びます。C++ はこれを C からコピーします。どちらの言語もこれをモジュラス演算子とは呼びません。これは、剰余が負である理由も説明しています。/ 演算子は 0 に向かって切り捨てられ、 と(a / b) * b + (a % b)等しくなるはずだからaです。

編集: David Rodríguez は、C++std::modulusを呼び出すテンプレート クラスを定義していることを正しく指摘していますoperator%。私の意見では、そのクラスの名前は不適切です。少し掘り下げると、すでに名前が付けられていたSTLをそのまま継承しています。STL のダウンロードには、「STL は SGI MIPSproTM C++ 7.0、7.1、7.2、および 7.2.1 で開発されました。」とありますが、実際にコンパイラとハードウェアを持っていなくてもわかる限り、MIPSpro は除算を CPU に渡し、 MIPS ハードウェアは 0 に切り捨てられます。これは、std::modulus常に誤った名前が付けられていることを意味します。

于 2012-02-14T21:50:42.600 に答える
5

%CおよびC++の剰余演算子です。

C ++標準では、%演算子と呼ばれ、除算から余りを生成します。C標準では%演算子と呼ばれ、C99以降は実際には剰余演算子です。モジュロ演算子と剰余演算子は、負の値に関して異なります。

%演算子は、CおよびC++で。を使用して定義されますa == (a / b * b) + a % b

Cの0に向かう整数除算の切り捨ては、C99以降に行われます。C89では、実装が定義されていました(%C89ではモジュロ演算子にすることができます)。C ++は、整数除算のためにゼロに向かって切り捨ても実行します。

切り捨てがゼロに向かって行われる場合、%は剰余演算子であり、結果の符号は被除数の符号です。切り捨てがマイナス無限大に向かって行われる場合、%はモジュロ演算子であり、結果の符号は除数の符号です。

Cが切り捨てに関する整数除算の実装定義の動作を変更した理由について、C委員会のDougGwynは次のように述べています。

C99は、より多くのFortranロゴラマーを引き付け、FortranコードをCに変換するのを支援するために、Fortran互換の要件を課しました。

C99の理論的根拠は、ゼロ整数除算に向けた切り捨てに関して次のように述べています。

ただし、Fortranでは、結果は常にゼロに向かって切り捨てられ、オーバーヘッドは数値プログラミングコミュニティに受け入れられるようです。したがって、C99でも同様の動作が必要になり、FortranからCへのコードの移植が容易になります。

実装ではgcc、C89の動作は常にゼロへの切り捨てでした。

C99 %、C ++、およびJavaの剰余演算子も同様ですが、すべてのプログラミング言語の剰余演算子ではありません。RubyとPythonでは%、実際にはモジュロ演算子です(これらの言語では、整数の除算はマイナス無限大に向かって行われます)。HaskhellとSchemeには、HaskellmodとSchemeの2つの別個の演算子があります。remmoduloremainder

于 2012-02-14T21:54:34.960 に答える