質問: 負の値/負の値 正の値/負の値 負の値/正の値 の計算や 負の値%負の値 正の値%負の値 負の値%正の値 の計算において 割り算の結果がコンパイラに依存していたり 剰余が負の値になったりするのはなぜですか 数学的には答えは一つに定まると思うのですが
回答: C++03までは仕様により処理系定義とされていたためです。`(a/b)*b + a%b = a`を満たしさえすれば(b≠0の場合)、剰余の符号はimplementation-definedとされていました。 ISO/IEC 14882:2003(E)より(ISO/IEC 14882:1998(E)も同様)(強調は私) > > 5.6 Multiplicative operators > > 4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, **the sign of the remainder is implementation-defined.** > > > C++11ではimplementation-definedの文言が消え、明確に挙動が定められました。 `(a/b)*b + a%b = a`を満たすことは変わっていませんが、`/`演算子による商の小数部は捨てられる、つまり0の方向に向かって切り捨てられるとされています。そうすると必然的にaが正の場合は剰余は正、aが負の場合は剰余は負と定まります。 ISO/IEC 14882:2011(E)より > > 5.6 Multiplicative operators > > 4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded; if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a. > > > 上記はC++の話。 Cについては仕様書を持っていないので明確なことは言えず申し訳ありませんが、本家SOの質問を見る限りやはりC89は処理系定義、C99で剰余の符号は第1オペランドと同符号となったようです。 根本的な疑問に回答していない気がしたのでさらに追記。 > > 数学的には答えは一つに定まると思うのですが > > > 商をどちらの方向に丸めるかはh2so5さんの回答のとおりコンピュータの都合です。 剰余については数学的にも一意に定まるものではありません。 除法 - Wikipediaに詳しいですが、例えば`-22÷4`を例にすると ``` −22 = (−6) × 4 + 2:商 −6, 剰余 2 −22 = 6 × (−4) + 2:商 6, 剰余 2 −22 = (−5) × 4 − 2:商 −5, 剰余 −2 −22 = 5 × (−4) − 2:商 5, 剰余 −2 ``` といった色々な考え方があり得ます。 したがって、一般にプログラム言語における除算、剰余算がどのように振る舞うかはその言語仕様が定め、仕様で定まらない場合はその処理系の実装依存、となります。