調べたきっかけ
Rubyのマニュアルを読んでいたところ、例に書いている負数割り算の余について、
疑問が湧いてきましたので、少し調べてみました。
「算術演算子」処理の例でしたが、
13 % 4 => 剰余: 1
13 % -4 => 剰余:-3
-13 % 4 => 剰余: 3
-13 % -4 => 剰余:-1
剰余として、
- 13 / 4 は、 商は3で、余が1でOK
- 13 / -4 は、 商は-3で、余が1ではなく、-3なの?
- -13 / 4 は、 商は-3で、余が-1ではなく、3??
- -13 / -4 は、 商は3で、余が-1でOK
と、想定していた余り値と、例に書いている値が異なっていて、
割り算ってどうしてたっけ・・・と、よくわからなくなりました。
そういえば、学生時代に習った数学では、
負数で、余の求めることはなかったような気がします。
たとえば、
- -13 ÷ 4 は、-13/4
- -13 ÷ -4 は、13/4
のように、計算(解答)して終わっていましたね。
そう・・・あんまり考えて計算していなかったんだ。それで、もう少し調べてみました!
負数の割り算を調べてみた
結論からいうと、
負数の割り算の計算法は複数存在しており、計算する対象や計算機の機種、
あるいは、プログラミング言語により、まちまちであると書いていました。
※詳しい説明は、色々数学用語が出てきていますので、リンクだけ張っておきます。
ご参考ください。
– wikipedia「除法」
– wikipedia「除法の原理」
– Division and Modulus for Computer Scientists
プログラムでの割り算では、丸め方法にも関わっていて、これも同じく、
プログラミング言語により異なっており、IEEE(浮動小数点数算術標準)丸め方法では、
- 最近接丸め(偶数) (round to the nearest)
- 0への丸め(rounding toward zero; RZ)
- 正の無限大への丸め(rounding toward minus infinity; RM)
- 負の無限大への丸め (rounding toward plus infinity; RP)
がありました。
※丸め方法の詳しい説明は、下記のリンクを参照してください。
RubyとMySQLの丸め
Rubyの場合は、「負の無限大への丸め」に丸められていました。
1 2 3 4 5 6 7 8 |
irb(main):001:0> 13 % 4 => 1 irb(main):002:0> 13 % -4 => -3 irb(main):003:0> -13 % 4 => 3 irb(main):004:0> -13 % -4 => -1 |
– Ruby2.4.0マニュアル「divmod」:The quotient is rounded toward -infinity…
MySQLは、結果からみると、
「0への丸め」で丸められた割り算が行っていることがわかります。
1 2 3 4 5 6 7 |
mysql> SELECT 13 % 4, 13 % -4, -13 % 4, -13 % -4; +--------+---------+---------+----------+ | 13 % 4 | 13 % -4 | -13 % 4 | -13 % -4 | +--------+---------+---------+----------+ | 1 | 1 | -1 | -1 | +--------+---------+---------+----------+ 1 row in set (0.00 sec) |
– MySQL 5.7 Reference Manual「DIV」:Discards from the division result any fractional part to the right of the decimal point
– MySQL 5.7 Reference Manual「TRUNCATE(X,D)」:All numbers are rounded toward zero
被除数 | 除数 | 結果 | 負の無限大への丸め(商…余) | 0への丸め(商…余) |
---|---|---|---|---|
13 | 4 | 3.25 | 3…1 | 3…1 |
13 | -4 | -3.25 | -4…-3 | -3…1 |
-13 | 4 | -3.25 | -4…3 | -3…-1 |
-13 | -4 | 3.25 | 3…-1 | 3…-1 |
※この例での丸め
a.「0への丸め」:0を基準で、小数点以下を0に近い数字に丸めます。
例では、-3.25 は-3、3.25は3に丸められます。
b.「負の無限大への丸め」:小数点以下を負の方面に丸めます。
例では、-3.25 は-4、3.25は3に丸められます。
結論
- プログラミングの言語により、負数の割り算計算式が異なっています。
- 精密な計算を要する計算式を使う場合、きちんと結果を想定しておく必要があります。
※Ruby+MySQLだと、Rubyでは「負の無限大への丸め 」、MySQLでは「0への丸め」
の方式で計算しているため、プログラム側で計算する際と、DBで計算する際の値が
異なる場合がありえます。
もっと安全にするためには、
- 負数の割り算を辞めるか、
- 各自、想定する計算処理を組んで使うほうがよいでしょう。