「関係演算子」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
m →‎その他: cl, 言い回し
m →‎論理的な等価: cl, 言い回し
172行目: 172行目:
[[PHP: Hypertext Preprocessor]]言語では、このシンタックスを拡張し、型が異なっても値が等しければ真を返す "<code>==</code>"演算子(例えば"<code>4 == "4"</code>"は真である)と、値が等しくかつ同じ型を持っている場合に真を返す "<code>===</code>"演算子(例えば "<code>4 === 4</code>" は真であるが "<code>4 === "4"</code>" は偽である)の2種類の演算子を持っている<ref name="php">{{cite web|url=http://php.net/manual/en/language.operators.comparison.php |title=PHP: Comparison Operators - Manual|accessdate=2008-07-31}}</ref>。"<code>x == 0</code>"はxが<code>0</code>、<code>"0"</code>(文字0を含む文字列)または <code>false</code>(PHPでは他の言語でも見られる様に、<code>false</code>は<code>0</code>と等しい )の時に真を返す。これは、変数に 0 の値が割り当てられているかを確認するのに便利であるが、必ずしも期待される動作とは限らない<ref name="php" />。一方で、"<code>x === 0</code>"は xが<code>0</code>の時のみ真を返す。
[[PHP: Hypertext Preprocessor]]言語では、このシンタックスを拡張し、型が異なっても値が等しければ真を返す "<code>==</code>"演算子(例えば"<code>4 == "4"</code>"は真である)と、値が等しくかつ同じ型を持っている場合に真を返す "<code>===</code>"演算子(例えば "<code>4 === 4</code>" は真であるが "<code>4 === "4"</code>" は偽である)の2種類の演算子を持っている<ref name="php">{{cite web|url=http://php.net/manual/en/language.operators.comparison.php |title=PHP: Comparison Operators - Manual|accessdate=2008-07-31}}</ref>。"<code>x == 0</code>"はxが<code>0</code>、<code>"0"</code>(文字0を含む文字列)または <code>false</code>(PHPでは他の言語でも見られる様に、<code>false</code>は<code>0</code>と等しい )の時に真を返す。これは、変数に 0 の値が割り当てられているかを確認するのに便利であるが、必ずしも期待される動作とは限らない<ref name="php" />。一方で、"<code>x === 0</code>"は xが<code>0</code>の時のみ真を返す。


==論理的な等価==
==論理的同値性==
[[ブール論理]]の[[論理演算]]子XOR、AND、OR、NOTように最初おそらく明らかではないがそれらがすべて互いにの項として定義できるように、関係演算子は、[[論理的等価]]持つようにデザインできる。以下の4つの条件すべて同じ論理的等価を持っている:
一見して自明ではないが、[[ブール論理]]の[[論理演算]]子 XOR、AND、OR、NOT と同じように、比較演算子は、互いに比較演算子を用いて論理的に同値な命題構成できる。以下の4つの条件互いに[[論理的同値性]]を持:
* <math>x < y</math>
* <math>x < y</math>
* <math>y > x</math>
* <math>y > x</math>

2011年3月17日 (木) 19:10時点における版

計算機科学において、関係演算子かんけいえんざんし)とは、2つのエンティティの間の或る種の二項関係をテストするプログラミング言語の構成要素または演算子の事を指す。例として、数の等値関係(5 = 5 など)や不等関係(4 ≥ 3 など)が挙げられる。Java などのように、型システムとしてブーリアン型を独立に用意している言語では、関係演算子は、二つのオペランドの間で対応する関係が満たされているかどうかに依って、真か偽の値を返す。一方で、C言語などの言語では、関係演算子は整数 0 または 1 を返す。

関係演算子を用いて形成されたは、関係式または条件として知られている。また、技術的な文献において、関係を言葉で説明する代わりに関係演算子が使用される事もある。関係演算子をサポートするプログラミング言語では、関係演算子は多くの場合中置記法によって記述される。すなわち、2つのオペランド(関係の対象となる式)の間に関係演算子が記される。例えば、以下のC言語の文は、xyより少ない場合にメッセージを表示する:

  if (x < y) {
      printf("x is less than y in this example\n");
  }

また、ポーランド記法を採用している言語もある。例えば、Lispでは以下のように記述する:

(>= X Y)

標準的な関係演算子

プログラミング言語の中で使用される標準的な数値比較演算子を以下に示す。

標準的な関係演算子
プログラミング言語中で 印刷物中で 意味 用途
C言語ライク 1 BASICライク 2 Mathematica[1] MATLAB 3 FORTRAN 4 Bourneライクシェル 5 MUMPS
== = == Equal[x,y] == eq(x,y) == .EQ. -eq = = 等しい 2つの値が等しいことをテストする。
!= <> != Unequal[x,y] ~= ne(x,y) /= .NE. -ne '= 等しくない 2つの値が等しくないことをテストする。
> > > Greater[x,y] > gt(x,y) > .GT. -gt > > より大きい 左の値が右の値より大きいことをテストする。
< < < Less[x,y] < lt(x,y) < .LT. -lt < < より小さい 右の値が左の値より小さいことをテストする。
>= >= >= GreaterEqual[x,y] >= ge(x,y) >= .GE. -ge '< 以上 (大きいか等しい) 左の値が右の値より大きいか等しいことをテストする。
<= <= <= LessEqual[x,y] <= le(x,y) <= .LE. -le '> 以下 (小さいか等しい) 右の値が左の値より小さいか等しいことをテストする。
註1: C言語C++C#GoJavaJavaScriptPerl(数値比較のみ)、PHP: Hypertext PreprocessorPythonRuby を含む。
註2: BASICObjective CamlPascalSQLStandard MLを含む。
註3: MATLABは、殆どの演算子ではC言語と同様のシンタックスを使用するが、!=を使用しない。MATLABで !は、以降のテキストをコマンドラインとしてオペレーティングシステムに送る働きを持つからである。
註4: Haskell を含む最初のフォーム。
註5: Bourne ShellKorn ShellWindows PowerShell を含む。シンボル<>はシェルの中では通常リダイレクトのために使用されるので、他の記号を用いる必要がある。頭のハイフンを除いた物は、Perl において文字列比較に使用される。

等式

代入演算子との混乱

C言語の広範囲に及んだ普及のため、他の多くのプログラミング言語はC言語の文法を参考にした。その典型的なものが、等値関係の関係演算子として標準的な "=" の代わりに "==" シンタックスを用いるという物である。この独特のシンタックスは、B言語開発の初期の段階で "=" を別の意味に割り当てたことに端を発する。(ALGOLFORTRANに影響を受けた)B言語のデザイナーは、タイピングを減らしたいという要望から、頻繁に記述される値の更新・(副作用を伴う)代入操作のためのコピー演算子として、標準的な等値演算子 "=" を代用することを決定したのである。これは、A=A+1 の様な一見して「不可能」な式が許容されることを意味する。数十年後、C言語の人気のため、この用法は Java、C#、その他いくつかの言語でも採用された。他方、等値演算子 "=" の本来の意味を留めている言語としては PascalObject PascalAdaStandard MLObjective CamlSQLVHDL などがある。

これらのC言語系統における"="の用法はバグの温床になる。プログラマーが "if (x == y)" の代わりに、"if (x = y)" とミスタイプすることがあるのである。C言語において、"if (x == y)"は大雑把に言えば「xy同値ならば以下のステートメントを実行せよ」を意味する。しかし、"if (x = y)"とミスタイプすると「xyの値を割り当て、もしxの新しい値が0でなければ、以下のステートメントを実行せよ」という意味になってしまう。(同じ演算子を持つ JavaC#も同じ問題を孕んでいるが、これらの言語ではこの誤りはコンパイルエラーとして検出できる。if 条件式はブーリアン型に制約を受け、また他の型(例えば整数型)からブーリアン型に暗黙的に変換されることもないからである。)例えば、"if (x = y)"と書いてしまうと、yxに代入され両方とも2になり、更にxの値2は0ではないので、常にステートメントが実行される。従って、以下のコードは"x is 2 and y is 2"を出力する。[2]

  int x = 1;
  int y = 2;
  if (x = y) {
      /* yが0でなければ以下のコードは常に実行される */
      printf("x is %d and y is %d\n", x, y);
  }

Ada と Python においては、(if節も含めて)の途中に代入演算子は登場できないので、この手の誤りは排除できる。GNUコンパイラコレクションなどのいくつかのコンパイラでは、if の条件式中に代入演算子を含んでいるコード (意図的に書かれることもある) をコンパイルするときに警告を出す。

同様に、BASIC などのいくつかの言語では、文法的に弁別できることから、代入と等式の両方に "=" 記号を使用する(Ada や Python と同様に、代入演算子は式中に出現することがない)。

プログラマーの中には予防策として、定数に対する比較を記述する時、以下の様に直感とは逆の順でオペランドを記述する者もいる。この様にしておけば、誤って "=" と書くと 2 は左辺値ではないので、書いたコードは不正になる。コンパイラはこれに対してエラーメッセージを出すので、結果、適切な演算子に修正できるのである。このコーディングスタイルは left-hand comparison として知られている。

  if (2 == a) {   /* =と==の誤用がコンパイルタイムエラーを引き起こす */
  }

オブジェクトの同一性と内容の同値性

多くの現代的なプログラミング言語において、オブジェクトとデータ構造は参照を通じてアクセスされる。そのような言語では、2種類の異なる等価性を判定する必要性が生じる:

  • 物理的な(浅い)等価 - 2つの参照が同じオブジェクトを参照するかどうか
  • 構造的な(深い)等価 - 2つの参照によって参照されたオブジェクトがある意味において(例えば内容が同じである)等しいかどうか

通常、前者の等価性は後者の等価性を暗示しているが(自身に等しくないような NaN のようなものは除く)、逆は必ずしも真ではない。例えば、2つの文字列オブジェクトは別個のオブジェクトであるかもしれない(前者の意味では等しくない)が、同じ文字の並びを持ちうる(後者の意味で等しい)。

次の表では、これらの2種類の等価性を判定するための異なる方法を、様々な言語において一覧できるようにしてある。

言語 物理的な等価 構造的な等価 注意
C言語, C++ a == b *a == *b abはポインタである
C# object.ReferenceEquals(a, b)1 a.Equals(b)1
Common Lisp (eq a b) (equal a b)
Java a == b a.equals(b) ab参照である
Objective Caml a == b a = b
Pascal a^ = b^ a = b
Perl $a == $b $$a == $$b $a$bはスカラーへの参照である
PHP: Hypertext Preprocessor5 N/A $a == $b $a$bはオブジェクトである
Python a is b a == b
Ruby a.equal?(b) a == b
Scheme (eq? a b) (equal? a b)
Microsoft Visual Basic .NET a Is b a = b
Objective-C a == b [a isEqual:b] abはオブジェクトへのポインタである

1C# では、==演算子はデフォルトで ReferenceEquals になるが、代わりに Equals を実行する様に演算子オーバーロードをすることができる。この事によって、構造的な等価性の方がより直感的と思われる型において、== で構造的な等価性を判定する様にできる。特に文字列比較において、この事が効果的である (Java で文字列比較は a.equals(b) と書かなければならないが、C# では a==b と書ける)。

その他

PHP: Hypertext Preprocessor言語では、このシンタックスを拡張し、型が異なっても値が等しければ真を返す "=="演算子(例えば"4 == "4""は真である)と、値が等しくかつ同じ型を持っている場合に真を返す "==="演算子(例えば "4 === 4" は真であるが "4 === "4"" は偽である)の2種類の演算子を持っている[3]。"x == 0"はxが0"0"(文字0を含む文字列)または false(PHPでは他の言語でも見られる様に、false0と等しい )の時に真を返す。これは、変数に 0 の値が割り当てられているかを確認するのに便利であるが、必ずしも期待される動作とは限らない[3]。一方で、"x === 0"は xが0の時のみ真を返す。

論理的同値性

一見して自明ではないが、ブール論理論理演算子 XOR、AND、OR、NOT と同じように、比較演算子は、互いに他の比較演算子を用いて論理的に同値な命題を構成できる。以下の4つの条件式は互いに論理的同値性を持つ:

脚注・出典

  1. ^ Relational and Logical Operators of Mathematica
  2. ^ Kernighan, Brian; Dennis Ritchie (1988) [1978]. The C Programming Language (Second edition ed.). Prentice Hall , 19
  3. ^ a b PHP: Comparison Operators - Manual”. 2008年7月31日閲覧。