関係演算子とは
関係演算子は、2つの値を比較して、その結果をtrue
またはfalse
のbool値で返すために使用されます。以下は、C#でよく使用される関係演算子の一覧です。
演算子 | 説明 | 例 | 結果 |
== | 等価 | a == b | aとbが等しければtrue |
!= | 不等 | a != b | aとbが等しくなければtrue |
> | 大なり | a > b | aがbより大きければtrue |
< | 小なり | a < b | aがbより小さければtrue |
>= | 大なりイコール | a >= b | aがbと等しいか大きければtrue |
<= | 小なりイコール | a <= b | aがbと等しいか小さければtrue |
比較演算子「==」を用いる時の注意点
StringBuilder sb1 = new StringBuilder("あいう");
StringBuilder sb2 = sb1;
sb1.Append("えお");
Console.WriteLine(sb1 == sb2);//結果true
StringBuilder sb3 = new StringBuilder("あいう");
StringBuilder sb4 = new StringBuilder("あいう");
Console.WriteLine(sb3 == sb4);//結果false
Console.WriteLine(sb3.Equals(sb4));//結果はtrue
上のサンプルでは代入演算子の所で説明した参照型の代入ですので、sb1、sb2は共に同じアドレスを指しているため、trueが帰ってきます。
それとは異なり9行目では追加したテキストが同一にも関わらず比較するとfalseになってしまいます。これはnewで新たにStringBuilderオブジェクト作成しているため、異なるアドレスにsb3とsb4が格納されているためです。
これでは困るということで全てのクラスにはEqualsメソッドが存在します。Equalsメソッドはクラスによって様々な動作をしますが、このStringBuiderクラスでは含まれる文字列を比較します。
補足1。文字列の比較は「==」を使用しよう
文字列型stringの値を比較するのはEqualsメソッドではなく比較演算子「==」を普通は使用します。
文字列の場合「==」演算子を上書きして内部的にはEqualsメソッドを呼び出すようにしています。
但し、Equalsメソッドはどんな型の引数も取れるので余り使用するべきではありません。
string data1 = "123";
int data2 = 123;
Console.WriteLine(data1.Equals(data2)); //結果はfalse
Console.WriteLine(data1 == data2); // コンパイルエラー
補足2.浮動小数点の比較について
浮動小数点の演算で丸め誤差等の思わぬ動作をする事がありますが、それは比較演算子を用いた時も同様です。比較する場合、以下の方法があります。
const double EPSILON = 0.00001;
double x = 0.2 * 3;
double y = 0.6;
Console.WriteLine(x == y); //結果はfalse
Console.WriteLine(Math.Abs(x - y)< EPSILON);//結果はtrue
Math.Absメソッドは引数の絶対値を取るものですが、比較したい浮動小数点の値の差がEPSILON未満であればそこまでは等しいと見做すことが出来ます。
補足3.配列の比較
配列の比較には「==」演算子も、Equalsメソッドも使えません。
string[] str1 = new string[]{"あ","い","う"};
string[] str2 = new string[]{"あ","い","う"};
Console.WriteLine(str1 == str2); //結果はfalse
Console.WriteLine(str1.Equlas(str2));//結果はfalse
比較する場合以下の方法がありますが、手間が掛かります。
string[] str1 = new string[] { "あ", "い", "う" };
string[] str2 = new string[] { "あ", "い", "う" };
bool ret = true;//戻り値にtrueを設定して、ひとつでも異なる点があればfalseにする
if (str1.Length == str2.Length)//配列str1とstr2の要素数が等しければ中身の比較をする
{
for (int i = 0; i < str1.Length; i++)
{
if (str1[i] != str2[i])//中身の値が異なる
{
ret = false;
break;
}
}
}
else //要素数が一致しないので等しくない
{
ret = false;
}
Console.WriteLine(ret);
いちいち実装するのも面倒なのでEnumerableクラスのSequenceEqualsメソッド(System.Linq名前空間:using句にSystem.Linqを加えることで使用できます)を用いて比較します
using System;
using System.Linq;//この一文を追加することでSequenceEqualsが利用可能となる。
class Program{
string[] str1 = new string[] { "あ", "い", "う" };
string[] str2 = new string[] { "あ", "い", "う" };
Console.WriteLine(str1.SequenceEqual(str2));
}
条件演算子(3項演算子)について
条件演算子は、指定された条件の真偽に応じて対応する式の値を返します。
int score = 75;
Console.WriteLine(score >= 70? "合格":"不合格");
上のサンプルはscoreが70以上であれば「合格」と出力し、それ未満だと「不合格」と出力します。
まとめ
今回は関係演算子を学びました。
値型と参照型で比較演算子「==」を用いる時には注意が必要です。値型は純粋に値の大小を比較してくれますが。ところが参照型の場合、格納されているアドレス同士が比較されてしまい、想定外の動作をします。従ってEqualsメソッドがあるのですが、StringBuilderクラスの場合、組み立てた文字列が等しいか否かで一致しているかどうかを判定してくれます。
また、浮動小数点同士の比較も要注意です。小数点以下の表現をすると丸め誤差が発生してしまい想定外の演算が行われてしまいます。従って、サンプルであげた方法で差分を取って比較する事でその誤差を減らせます。
コメント