演算子・被演算子・式

算術演算

前回は数値リテラルの使い方を学びました。
せっかく数値が扱えるようになったのですから、これを利用して何かをしたいところです。
というわけで、まずは簡単に四則演算をさせてみたいと思います。
コンピュータは『計算機』といわれるくらいですから、その程度は簡単にやってもらわないと困りますね。
というわけで、ソースはこんな感じです。

puts 1 + 2  # 足し算
puts 5 - 3  # 引き算
puts 9 * 9  # 掛け算
puts 18 / 6 # 割り算

↓実行すると……

3
2
81
3

こうなります。
掛け算の記号が『*』で、割り算の記号が『/』だということくらいに気をつければ、まったく予想通りの結果だと思います。
このときに利用した[+-*/]と言った記号を、“演算子”(operator: オペレータ)と呼びます。
特に今回使用したものは四則演算を行う演算子なので、“算術演算子”などと呼ばれることがあります。
また、演算子が作用する対象を“被演算子”(operand: オペランド)と呼びます。
例えば先ほどの例のうち、

18 / 6

における演算子は『 / 』で、オペランドは『 18と6 』になります。
さらに、この場合の演算子/はオペランドを2つ持ちます。このような演算子を“二項演算子”と呼びます。
オペランドが一つの演算子は“単項演算子”、3つだったら“三項演算子”などになります。
そして、『演算子とそれに必要なオペランドが成立した状態』を“演算子式”或いは単に“式”(expression)と呼びます。

式について、リファレンスの解説を確認してみましょう。

Ruby の式には、変数と定数、さまざまなリテラル、それらの 演算や代入、if や while などの制御構造、 メソッド呼び出し、クラス/メソッドの定義があります。

式は括弧によってグルーピングすることができます。

空の式 () は nil を返します。

Rubyの式には値を返す式と返さない式があります。

この説明の中で現在わかっているのは、

というあたりでしょうか。


今まで学んできた文字列リテラルや数値リテラル
あれらはデータとしての文字列や数値を表していると同時に、Rubyの言語構造の中では“式”と呼ばれる要素として扱われている、ということのようです。
また、メソッドの呼び出し――今まで利用した例だと、printやputsですね。これもまた“式”である、という点でリテラルと同じレベルで解釈されるようです。
そして、それらの式(の単一項)は、演算子によって組み合わせることが可能らしい、ということを知りました。


ところで、式の解説の中に気になる文があります。

Rubyの式には値を返す式と返さない式があります。

値を『返す』とはどういうことなのでしょうか。

式の評価

実は、Rubyにおける“式”という存在は、それ自体が解釈(実行・処理)された後の“値”を持ちます。
これを“式の値”と呼びます。
そして、この式の値を導き出す(ために計算やメソッドの呼び出しなどをする)ことを“式の評価”“式を評価する”と言います。
これは少々特殊な言い回しのようにも感じられますが、よく使われる言葉です。
例で考えてみます。

256

これは単に256という数値リテラルです。
しかし、先ほど学んだように、リテラルもそれ自体が式となります。式であるということ、はそれを“評価できる”ということにもなります。
実際、これを式として評価した場合、256というそのままの値を得が得られます。これがこの式の“式の値”になります。
言い回しを変えてみると、「上記の式を評価すると、256という値が返される」などと言えます。

0b100000000 + 0x100

では、このような場合はどうでしょうか。
今回は数値リテラルが2つありますね。まずは、この2つの式をそれぞれ評価します。
まず左辺(この場合、左オペランドとも)は2進整数リテラルですが、これを10進数に変換します(前回やりました)。

1 × 2^(9 - 1) → 1 × 2^8 → 1 × 256 → 256

次に右辺(右オペランド)は16進整数リテラルです。

1 × 16^(3 - 1) → 1 × 16^2 → 1 × 256 → 256

これで、両辺の式の値が得られました。
そして演算子「+」は、これら両辺の式の値に対して演算を行います。

256 + 256 → 512

これが、「0b100000000 + 0x100」という演算子式の式の値になります。
さて。この式がまたもや値を持つということは、この式に対してさらなる演算が可能だということです。
つまり、

0b100000000 + 0x100 * 0o400

という演算も可能になります。

演算子の優先順位

……と終わってしまうと、実は微妙です。
確かに上の式は演算可能なのですが、「0b100000000 + 0x100」の式の値に対する演算、ではなくなっています。
実のところ、普通の計算がそうであるように、Rubyでも乗除は加減演算よりも先に評価されるというルールがあります。
リファレンスをよく確認してみましょう。
演算子式
ここに、演算子の一覧が挙げられています。
この一覧は演算子の“優先順位”の高い順に掲載されているようです。
すなわち、演算子式の中に複数の演算子が登場するとき、各式はここに挙げられている順序で評価される、ということです。


これを踏まえて考え直してみると、先ほどの例で足し算を先に評価したい場合、

(0b100000000 + 0x100) * 0o400

このように優先したい式を括弧でくくって、優先順位を調整する必要があります。

残された気になる点

これで式のこともわかったし、取り敢えず算術演算はできるようになったので多少なりともプログラムらしい感じに近づきつつあります。
しかし、次のコードを試したときに少し不安になりました。

puts 11 / 3

これは割り切れない計算なので、答えは「3.66666...」のようになるはずです。
実際電卓で計算することこんな感じです。

ところが、Rubyに計算させると

3

とだけ返してきます。これはゆとり教育の賜物でしょうか。


.
.
.


また、リファレンスマニュアルの演算子式の解説に、次のような文があります。

ほとんどの演算子は特別な形式のメソッド呼び出しですが、一部のものは言語に組み込みで、再定義できません。

え、演算子はメソッド??
突然言われると何のことやら……です。突然でなくても面食らいますが。
しかも再定義できるとかできないとか。演算子の意味を変えられるとでも言うのでしょうか。
これはもう少し別の視点で見直す必要がありそうです。



……と、そんなわけで。
次回はクラスとメソッドについてさらっと学ぶ予定です。