Ruby/MySQLでの負数割り算について

0への丸め/負の無限大への丸め
この記事は最終更新から6年以上経過しています。内容が古くなっている可能性があります。

調べたきっかけ

Rubyのマニュアルを読んでいたところ、例に書いている負数割り算の余について、
疑問が湧いてきましたので、少し調べてみました。

「算術演算子」処理の例でしたが、

13 % 4 => 剰余: 1
13 % -4 => 剰余:-3
-13 % 4 => 剰余: 3
-13 % -4 => 剰余:-1

※Integerの算術演算子「%」

剰余として、

  • 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)

がありました。
※丸め方法の詳しい説明は、下記のリンクを参照してください。

– wikipedia「端数処理-コンピュータでの丸め」

RubyとMySQLの丸め

Rubyの場合は、「負の無限大への丸め」に丸められていました。

– Ruby2.4.0マニュアル「divmod」:The quotient is rounded toward -infinity…

MySQLは、結果からみると、
「0への丸め」で丸められた割り算が行っていることがわかります。

– 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

※この例での丸め
0への丸め/負の無限大への丸め
 a.「0への丸め」:0を基準で、小数点以下を0に近い数字に丸めます。
  例では、-3.25 は-3、3.25は3に丸められます。
 b.「負の無限大への丸め」:小数点以下を負の方面に丸めます。
  例では、-3.25 は-4、3.25は3に丸められます。

結論

  • プログラミングの言語により、負数の割り算計算式が異なっています。
  • 精密な計算を要する計算式を使う場合、きちんと結果を想定しておく必要があります。

※Ruby+MySQLだと、Rubyでは「負の無限大への丸め 」、MySQLでは「0への丸め」
 の方式で計算しているため、プログラム側で計算する際と、DBで計算する際の値が
 異なる場合がありえます。

もっと安全にするためには、

  • 負数の割り算を辞めるか、
  • 各自、想定する計算処理を組んで使うほうがよいでしょう。
よかったらシェアしてね!
  • URLをコピーしました!
目次