加減乗除などの基本的な数値演算について書かれた Ruby の初心者向け記事で,よく
Ruby の算術演算(or 四則演算,加減乗除 etc)は他の言語と変わりません。
などとして,例えば
puts 20 + 30 # => 50
puts 16 - 9 # => 7
puts 20 * 3 # => 60
puts 60 / 3 # => 20
puts 10 % 3 # => 1
といったコードサンプルが書かれていることがあります。
Qiita でも,年に何本かそういう記事が書かれています。
もちろん「変わる(違いがある)」かどうかは「他の言語」が何であるかによるわけですが,まあ「わりとメジャーな普通っぽい多くの言語」くらいのつもりで書かれているのだと思います。
和・差・積はともかくとして,商と剰余は要注意ですよ。これは言語によってさまざまです。
このコードサンプルの除算で,割り切れるような数が選ばれているのは意図してでしょうか。
割り切れない数の場合にどうなるかは知っておきたいところです。
Ruby では,被除数(割られる数)と除数(割る数)がともに Integer オブジェクトの場合,/
による除算は「整除法」になります。整除法は商が整数になるよう定義された割り算のことですね。
puts 10 / 4 # => 2
一方が Integer オブジェクトでない場合は整除法になりません。
puts 10.0 / 4 # => 2.5
puts 10r / 4 # => 5/2
上の例で,10r
というのは数学的に 10 に等しい Rational オブジェクト(有理数オブジェクト)です。「分母が 1 で分子が 10 の有理数オブジェクト」ですね。
10r / 4
の結果は「2 分の 5」という Rational オブジェクトになります。
このような,整数オブジェクト同士の /
による除算が整除法になるのは Ruby の著しい特徴です。JavaScript も PHP も
10 / 4
は浮動小数点数の 2.5
になります1。
さて,整除法についてしっかり把握すべき点が一つあります。それは被除数・除数の少なくとも一方が負数の場合にどうなるか,です。
Ruby は除数が正のとき,被除数の符号に関わらず,整商(整除法における商)は「0 以上,除数未満」の値になります。これは数学的には最もなじみのある自然な整除法の定義ですが2,プログラミング言語ではむしろ少数派ではないかと思います。
puts -10 / 4 # => -3
puts 10 / -4 # => -3
puts -10 / -4 # => 2
もう一つ大事なことは,Ruby の除算は /
によるものだけではない,ということです。
まず,被除数・除数の型に関わらず浮動小数点数の商が欲しい場合,Numeric#fdiv が使えます。
puts 10.fdiv(4) # => 2.5
一方,被除数・除数の型に関わらず整商が欲しい場合,Numeric#div を使います。
puts 10.0.div(4.0) # => 2
puts 3.5.div(1.5) # => 2
上のコードの二つ目の例のように,整数でない数同士でも整商が得られる,ということが大事ですね3。
逆に,被除数・除数の型に関わらず普通の商が欲しい場合,Numeric#quo を使います。
puts 10.quo(4) # => 5/2
puts 10.0.quo(4) # => 2.5
Integer 同士の場合,割り切れるなら Integer で返し,割り切れない場合は Rational で返すのが特徴です。
以上で分かるとおり,60 / 3
の結果だけ見て「Ruby の除算は他の言語と同じ」などと言うわけにはいかないのです。
除算について述べるなら剰余についても述べるべきですが,この記事で注意喚起したかったことは以上で尽きているので割愛します。
訂正(2023-01-02)
この記事ではもともと整除法のことを「整除」と書いていましたが,整除は意味が異なる用語であることに気づき,「整除法」に訂正しました。