関係演算子

計算機科学において、関係演算子（かんけいえんざんし、"relational operator"）または比較演算子（ひかくえんざんし、"comparison operator"）とは、プログラミング言語の演算子で、2つの対象の関係を調べるものをいう。たとえば、同値関係を調べる等号（formula_1 の formula_2）や、順序関係を調べる不等号（formula_3 の formula_4）などが含まれる。
JavaやC#など、独立したブーリアン型を型システムに持つ言語では、関係演算子は2つのオペランドの間に演算子が表す関係が成り立つかどうかによって真 (true) または偽 (false) を返す。一方で、C言語などのブーリアン型を持たない初期の言語では、関係演算子は整数 0（偽を意味する）または 1（真を意味する）を返す。
関係演算子を含む式は、関係式 ("relational expression") または条件 ("condition") と呼ばれる。また、技術的な文献において、関係を言葉で説明する代わりに関係演算子が用いられることもある。多くのプログラミング言語では、関係演算子は中置記法で記述される。たとえば、以下のC言語のコードは、"x" が "y" より小さい場合にメッセージを表示するものである。
if (x < y) {
 printf("x is less than y in this example\n");
他方で前置記法を採用している言語もある。たとえば、Lispでは以下のように書く。しかしこれは演算子というよりも、Lispでは識別子に使える文字の範囲が緩くて、単に codice_1 という名前の関数であるというだけである。
 (display "x is greater than or equal to y in this example"))
標準的な関係演算子.
多くのプログラミング言語で使用されている標準的な数値比較演算子を以下に示す。
等号.
代入演算子との混乱.
C言語から直接または間接的に派生したプログラミング言語では、同値関係の関係演算子として、直感的な codice_2 ではなく codice_3 を用いる。一方、codice_2 を用いる言語としては Pascal、BASIC、Ada、Standard ML、Objective Caml、SQL、VHDL などがある。
C言語は広範囲に普及したため、後発のプログラミング言語における構文や仕様はC言語のそれを参考に定義されたものも多いが、そのうちの一つがこの codice_3 演算子である。この独特の構文は、B言語開発の初期の段階で codice_2 を別の意味に割り当てたことに端を発する。ALGOLとFORTRANの流れを汲むB言語の設計者は、タイピングを減らしたいという要望から、頻繁に記述される更新・代入操作のためのコピー演算子として codice_2 を代用することを決定したのである （これは codice_8 のような、一見して「数学的には不成立」な式が許容されることを意味する）。代わりに、codice_2 が本来担う役割である等号として codice_3 が使われることとなった。C言語はこれらの演算子をそのまま引き継ぎ、以後 Java や C# をはじめとする多くの言語がこの構文を採用したのである。
これらのC言語ファミリーにおける codice_2 の用法はバグの温床になりうる。C言語にはブーリアン型がなく、if文やwhile文の条件式には真偽値に評価されうる任意の数値型の式を受け付ける（ゼロあるいはゼロ相当を偽、非ゼロを真とする）。またC言語における代入は文ではなく式であり値を持つ。そのため、プログラマーが codice_12 の代わりに、codice_13 とミスタイプしても構文的には合法となってしまうのである。C言語において、codice_12 は大雑把に言えば「"x" と "y" が等しければ後続の文を実行せよ」を意味する。しかし、codice_13 とミスタイプすると「"x" に "y" の値を割り当て、もし "x" の新しい値が0でなければ、後続の文を実行せよ」という意味になってしまう。たとえば、下記の例で codice_13 と書いてしまうと、"y" が "x" に代入され両方とも2になり、更に "x" の値2は0ではないので、常に if 文のブロックが実行される。したがって、以下のコードは "x is 2 and y is 2" を出力する。
int x = 1;
int y = 2;
if (x = y) {
 /* yが0でなければ以下のコードは常に実行される */
 printf("x is %d and y is %d\n", x, y);
他の言語やコンパイラの中には、このようなミスを事前に防ぐように工夫されているものもある。
また、プログラマーの中には予防策として、定数に対する比較を記述するとき、以下のように直感とは逆の順でオペランドを記述する者もいる。このようにしておけば、誤って codice_2 と書くと 2 は左辺値ではないので、書いたコードは不正になる。コンパイラはこれに対してエラーメッセージを出すので、結果、適切な演算子に修正できるのである。このコーディングスタイルはヨーダ記法や left-hand comparison として知られている。ただしこの記法には、比較対象の少なくとも片方が左辺値を持たないような場合にしか使えない、多くの場合は重要な側の式が後から現れることになる、といった欠点がある。
if (2 == a) { /* 仮に = と == を誤用した場合はコンパイルエラーを引き起こす */
PHP での拡張.
PHPでは、codice_3 演算子をさらに拡張し、型が異なっても値が等しければ真を返す codice_3 演算子（たとえば codice_22 は真である）と、値が等しくかつ同じ型を持っている場合に真を返す codice_23 演算子（たとえば codice_24 は真であるが codice_25 は偽である）の2種類の演算子を持っている。codice_26 は "x" が codice_27、codice_28（文字 0 を含む文字列）または codice_29（PHPでは他の言語でも見られるように、codice_29 は codice_27 と等しい）のときに真を返す。これは、変数に 0 の値が割り当てられているかを確認するのに便利であるが、必ずしも期待される動作とは限らない。一方で、codice_32 は "x" が codice_27 のときのみ真を返す。
オブジェクトの同一性と内容の等価性.
多くの現代的なプログラミング言語において、オブジェクトやデータ構造は参照を通じてアクセスされる。そのような言語では、2種類の異なる等価性を判定する必要性が生じる:
通常、前者の等価性は後者の等価性を含意しているが（自身に等しくないような NaN のようなものは除く）、逆は必ずしも真ではない。たとえば、2つの文字列オブジェクトは別個のオブジェクトであるかもしれない（前者の意味では等しくない）が、同じ文字の並びを持ちうる（後者の意味で等しい）。
次の表では、これらの2種類の等価性を判定するための異なる方法を、様々な言語において一覧できるようにしてある。
論理的同値性.
一見して自明ではないが、比較演算子は、互いにほかの比較演算子を用いて論理的に同値な命題を構成できる。これは、ちょうどブール論理の論理演算子 XOR、AND、OR、NOT の間で見られる関係に似ている。以下の4つの条件式は互いに論理的同値である。
さらに、等号も不等号を用いて表現することができる。
この性質をプログラミングに応用して、不等号 ≥ だけ（または、≥ と = の二つだけ）を真面目に実装し、ほかの比較演算子を ≥（または、≥ と =）を用いて定義することも行われる。