負の数を含む Ruby のモジュロ規則は不明確です。IRB では:
-7 % 3 == 2
する必要があります1
!なんで?
-7/3 は、Ruby の整数除算のセマンティクスでは -3 であるためです。3*-3 は -9 なので、余りは 2 になります。
docsによると、 x modulo y は次のように定義されます。
x-y*(x/y).floor
オペランドの 1 つ%
が負の場合、返される結果について明確な最良の答えはありません。すべてのプログラミング言語には独自のルールがあります。モジュロ演算のウィキペディアのページには、各プログラミング言語がこれをどのように処理することを決定したかを示す巨大な表があり、明確なコンセンサスはありません。
$ # Modulus sign is:
$
$ curl 'http://en.wikipedia.org/w/index.php?title=Modulo_operation&action=edit§ion=1' \
| egrep -o 'Divisor|Dividend|Always positive|Closest to zero|Not defined|Implementation defined' \
| sort | uniq -c | sort -nr
67 Dividend
42 Divisor
7 Always positive
4 Closest to zero
2 Not defined
2 Implementation defined
左側のオペランドの符号を選択するものもあれば、右側のオペランドを選択するものもあります。他は指定しません。たとえば、C プログラミング言語は次のように 述べています。
% [is] の結果の符号は、負のオペランドの場合はマシンに依存します
これを処理する方法について特定の選択を行う代わりに、C は、使用されている特定のハードウェアまたはコンパイラが実装することを選択したものを返すだけです! これは、C プログラミング言語標準の最近のバージョンで標準化されているようです。
Ruby で特定のバージョンを取得したい場合は、 と という 2 つの異なるメソッドを呼び出すことができ、負modulo
の%
remainder
数に対して異なる動作をします。
$ irb
irb(main):001:0> -7.modulo(3)
=> 2
irb(main):002:0> -7.remainder(3)
=> -1
このための組み込みメソッドを持たない他の言語では%
、目的の記号を取得するために 2 回使用することになる場合があります。