12660


負の値/負の値  
正の値/負の値  
負の値/正の値

の計算や

負の値%負の値  
正の値%負の値  
負の値%正の値

の計算において

割り算の結果がコンパイラに依存していたり  
剰余が負の値になったりするのはなぜですか

数学的には答えは一つに定まると思うのですが


CC BY-SA 3.0
2015-07-24T10:52:26.543
12649
2015-07-24T16:57:51.483
2015-07-24T11:03:52.967
8000
10455
question
c++ c
負の値を含む割り算や剰余の計算結果がコンパイラによって異なるのはなぜ？


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の質問](https://stackoverflow.com/questions/13208287/remainder-
operator-in-c89-and-c99)を見る限りやはりC89は処理系定義、C99で剰余の符号は第1オペランドと同符号となったようです。

* * *

根本的な疑問に回答していない気がしたのでさらに追記。

> 数学的には答えは一つに定まると思うのですが

商をどちらの方向に丸めるかはh2so5さんの回答のとおりコンピュータの都合です。

剰余については数学的にも一意に定まるものではありません。  
[除法 -
Wikipedia](https://ja.wikipedia.org/wiki/%E9%99%A4%E6%B3%95)に詳しいですが、例えば`-22÷4`を例にすると

[code]

    −22 = (−6) × 4 + 2：商 −6, 剰余 2
    −22 = 6 × (−4) + 2：商 6, 剰余 2
    −22 = (−5) × 4 − 2：商 −5, 剰余 −2
    −22 = 5 × (−4) − 2：商 5, 剰余 −2
    
[/code]

といった色々な考え方があり得ます。

したがって、一般にプログラム言語における除算、剰余算がどのように振る舞うかはその言語仕様が定め、仕様で定まらない場合はその処理系の実装依存、となります。


CC BY-SA 3.0
2015-07-24T14:55:06.990
12660
2015-07-24T16:57:51.483
2017-05-23T12:38:56.467
-1
4765
12649
answer