講座全体の概要
プログラミング基礎講座の第7回、演算子についての解説です。講座全体の概要は以下の記事ゼロから始めるプログラミング基礎講座 第1回【講座の概要・目的】をご覧ください。
演算子とは
演算子とは+、–、=、==、>、<等の特別な記号のことで、記号の左右に記述した値や変数を対象に、そろぞれの記号に応じた演算処理が行われます。これらの演算子はいくつかの種類に分けられます。これまでの講座で登場した演算子も含め、改めて良く使われる演算子を紹介します。
オペランド
演算の対象となるものをオペランドといいます。例えば、x + yという式のx、yがオペランドです。特に、演算子の左側(例ではx)を左オペランド、演算子の右側(例ではy)を右オペランドと言います。あまり使わない言葉ですが、言語のヘルプやリファレンス等を見た時にオペランドという記載がされていることがありますので覚えておきましょう。
算術演算子
四則演算等のいわゆる計算を行うための演算子です。四則演算の一般的優先順位がそのまま適用されます。例えば、1 + 2 * 3 – 4 / 2 は1 + (2 * 3) – (4 / 2)と同じ意味であり、結果は5になります。( )により優先順位を明示することで優先順位を変更することも可能です。優先順位が同じ場合は左から順に計算がされます。
+(加算)
左オペランドが数値の場合は、加算(足し算)を行います。この場合、右オペランドも数値である必要があります。なお、数字(数を表す文字列)を数値として扱うためには、数字を解析して変換する必要があります。int.Parse(数字)でint型に変換できます。他の数値型も同様にParse(パース)という機能が用意されています。ただし、半角数字以外の文字列を指定した場合、プログラムを実行した時にエラーになります。以下の例を参考に、実際に試して動作を確認してください。
int a;
int x = 5;
string y = "7";
string z = "七";
a = x + y; // 「型 'string' を 'int' に暗黙的に変換できません」というエラーになる。
a = x + int.Parse(y); // 5 + 7 が計算される。
a = x + int.Parse(z); // 「「System.FormatException: 'Input string was not in a correct format.'」というエラーになる。
この様にエラーにも大きく分けて2種類あり、実行する前から発生するエラーをコンパイルエラー、実行時に発生するエラーを実行時エラー(ランタイムエラー)と言います。
コンパイルエラーはVisual Studioで赤く表示されるため、すぐにわかります。実行時エラーはデバッグ実行で確認するまでわかりません。
+(文字列結合)
+は算術演算だけではなく、文字列の結合にも使用されます。左オペランドが文字列の場合に、文字列の結合として解釈されます。この場合、右オペランドが数値であっても、自動的に数字へ変換されて文字列として結合されます。数値から文字列への変換ではエラーが発生しないため、自動的に変換が行えます。逆に、先ほどの例の様に自動的(暗黙的)に変換できないものは注意が必要です。
文字列結合の方法は、プログラミング言語によっては、これと異なる場合があります。
string a;
string x = "5";
string y = "7";
int z = 10;
a = x + y; // "57"という文字列になる。
a = x + z; // "510"という文字列になる。
−(減算)
減算(引き算)を行います。また、-5の様に、右オペランドのみの場合はマイナス値を表します。正確にはマイナス1を掛けた値になります。
*(乗算)
乗算(掛け算)を行います。特に注意事項はありません。
/(除算)
除算(割り算)を行います。除数(割る数)が0の場合は実行時エラーとなるので注意が必要です。また、オペランドがint型等の整数の場合は、小数点以下の計算はされません。小数点を含む計算を行う場合はDecimal型等の浮動小数点型を使用してください。ただし、浮動小数点の計算では誤差が発生する可能性があり、有効桁数に注意する必要があります。
int a;
int x = 5;
int y = 2;
int z = 0;
a = x / y; // 5 ÷ 2 = 2 となる。
a = x / z; // 「System.DivideByZeroException: 'Attempted to divide by zero.'」という実行時エラーになる。
%(剰余)
剰余(割り算した余り)を計算する演算子です。偶数、奇数の判断で良く使われます。また、除算と同じで除数が0の場合は実行時エラーとなります。
int x = 4;
int y = 5;
if (x % 2 == 0)
{
// 2で割った余りが0なので、xは偶数だとわかる。
}
if (y % 2 == 1)
{
// 2で割った余りが1なので、yは奇数だとわかる。
}
++(インクリメント)
オペランドに1を加算します。オペランドは変数やプロパティ等となります。x++(後置インクリメント)、++x(前置インクリメント)の様に、2種類の記述方法があり、加算がされるタイミングが異なります。以下の例を参考に、デバッグ実行で動作を確認してください。
int x = 1;
int y = 1;
int a = x++; // xはaに現在の値を代入した後に1が加算される。結果としてaは1になる。
int b = ++y; // yに1を加算した後に、bに代入される。結果としてbは2になる。
int c = x + y; // x、yともに上で1が加算されて2になっている。結果としてcは4になる。
−−(デクリメント)
オペランドから1を減算します。その他はインクリメントと同様です。
代入演算子
=
一般的に利用する代入演算子は=のみです。左オペランドに代入先の変数やプロパティを指定し、右オペランドには代入したい値や変数、プロパティ等を指定します。
C#では他にも代入演算子がありますが、オブジェクト指向プログラミングに深く係わる内容ですので今回は紹介しません。
算術演算子と代入演算子の複合
算術演算子の+–*/%と代入演算子=を組み合わせて、記述を省略できます。
例えば
x += y
は以下の文と同じ意味になります。
x = x + y
+=演算子は数値の加算、文字列の結合のどちらも可能ですが、左オペランド(上の例ではx)の型により演算が決定されます。右オペランドには、先に説明した+演算子と同じ規則が適用されます。
等値演算子
2つの値を比較して等しいか、等しくないかを評価してbool型の結果を返します。(処理した結果を出力することを、結果を返すと言います。)
左右のオペランドの型が同じであれば、数値以外も比較が可能です。
==(等価)
左右のオペランドが等しい場合にtrue、それ以外の場合にfalseを返します。
厳密には等値と等価では意味が異なりますが、オブジェクト指向プログラミングに深く係わる内容なので今回は説明を省きます。現段階ではどちらも「等しい」という認識でかまいません。
!=(非等値)
左右のオペランドが等しくない場合にtrue、それ以外の場合にfalseを返します。
比較演算子
数値型の2つの値について、その大小を比較してbool型の結果を返します。
>(大なり)
左オペランドが右オペランドより大きい場合にtrue、それ以外の場合にfalseを返します。
<(小なり)
左オペランドが右オペランドより小さい場合にtrue、それ以外の場合にfalseを返します。
>=(以上)
左オペランドが右オペランド以上の場合にtrue、それ以外の場合にfalseを返します。
<=(以下)
左オペランドが右オペランド以下の場合にtrue、それ以外の場合にfalseを返します。
論理演算子
bool型の値(true/false)を論理演算した結果を返します。条件式の複合や、否定条件を判定する際に使用します。論理演算になじみのない方のために、まず、論理演算の説明をします。
論理演算は以下の4種類です。
否定(NOT)
NOT AはAの反対の値を返します。すなわち、Aがtrueならばfalse、Aがfalseならばtrueを返します。
論理和(OR)
A OR Bは、AとBのどちらか一方でもtrueならばtrue、AとBのどちらもfalseならばfalseを返します。
論理積(AND)
A AND Bは、AとBの両方がtrueならばtrue、AとBのどちらか一方でもfalseならばfalseを返します。
排他的論理和(XOR)
A XOR Bは、AとBのどちらか一方のみがtrueならばtrue、それ以外はfalseを返します。
一般的なプログラミングではほとんど使われませんが、電子回路や複雑な論理演算が必要な分野では良く使われます。
C#における論理演算子は以下の通りです。
!(NOT)
!Aの様に記述します。A!と記述すると論理演算とはまったく異なる処理となりますので、!は必ずオペランドの前に記述してください。
||(OR)
|を2つ続けて記述します。なお、|1つだけでもORの演算になりますが、条件式の評価方法に違いがあり、特に意図がない限りは||を利用します。違いは、左オペランドのみで論理演算の結果が判断できる場合に、右オペランドを評価するか否かです。||は必要なければ右オペランドの評価を行いません。下の例を参考に、デバッグ実行で動作を確認してください。
int x = 1;
int y = 2;
int z = 3;
// 1つ目の条件式(y >= x)がtrueなので2つ目は評価しなくても論理演算の結果はtrueになるが・・・
if ((y >= x) |
(z >= ++y))
{
int yの値確認 = y; // 「|」の場合は2つ目も必ず評価されるため、「++y」が実行されてyは3になる。
}
x = 1;
y = 2;
z = 3;
// 1つ目の条件式(y >= x)がtrueなので2つ目は評価しなくても論理演算の結果はtrueになるので・・・
if ((y >= x) ||
(z >= ++y))
{
int yの値確認 = y; // 「||」の場合は2つ目は評価されないため、「++y」は実行されずにyは2のまま。
}
x = 1;
y = 2;
z = 3;
// 1つ目の条件式(y < x)がfalseなので2つ目を評価しないと論理演算の結果はわからないので・・・
if ((y < x) ||
(z >= ++y))
{
int yの値確認 = y; // 「||」でも2つ目が評価されるため、「++y」が実行されてyは3になる。
}
ちなみに|という記号は呼び方が色々あって、バーティカルラインや、バーティカルバー、縦棒、パイプ等と呼ばれます。日本で一般的に使用されている日本語配列キーボードだと、右上角にある「back space」キーの左隣りにあり、「shift」キーと一緒に押すことで入力できます。
&&(AND)
&を2つ続けて記述します。なお、&1つだけでもANDの演算になりますが、条件式の評価方法に違いがあり、特に意図がない限りは&&を利用します。違いはORと同様に、左オペランドのみで論理演算の結果が判断できる場合に、右オペランドを評価するか否かです。&&は必要なければ右オペランドの評価を行いません。
^(XOR)
A ^ Bの様に記述します。ちなみに^という記号は、ハット、キャレット等と呼ばれます。日本で一般的に使用されている日本語配列キーボードだと、右上角にある「back space」キーの2つ左にあります。
ド・モルガンの法則
数学で集合について学習した方や、論理演算になじみのある方は聞いたことがあると思いますが、「ド・モルガンの法則」という法則を覚えておくと、プログラミングにおいても複合条件をよりわかりやすく置き換えたりすることができます。法則の名前はどうでもいいですが、その内容をC#の文法で表すと以下通りとなります。
・ !(条件式A || 条件式B) は !条件式A && !条件式B と等しい
・ !(条件式A && 条件式B) は !条件式A || !条件式B と等しい
以下のコードではtrueとfalseの組み合わせごとに、上記の2つの法則の左側と右側で論理演算の結果が等しくなることを確認しています。デバッグ実行すると、result1、およびresult2が全てtrueとなっていることがわかります。
bool 条件式A;
bool 条件式B;
bool result1;
bool result2;
条件式A = true;
条件式B = true;
result1 = !(条件式A || 条件式B) == (!条件式A && !条件式B);
result2 = !(条件式A && 条件式B) == (!条件式A || !条件式B);
条件式A = true;
条件式B = false;
result1 = !(条件式A || 条件式B) == (!条件式A && !条件式B);
result2 = !(条件式A && 条件式B) == (!条件式A || !条件式B);
条件式A = false;
条件式B = true;
result1 = !(条件式A || 条件式B) == (!条件式A && !条件式B);
result2 = !(条件式A && 条件式B) == (!条件式A || !条件式B);
条件式A = false;
条件式B = false;
result1 = !(条件式A || 条件式B) == (!条件式A && !条件式B);
result2 = !(条件式A && 条件式B) == (!条件式A || !条件式B);
上記の例はまだ単純なのでいいのですが、たくさんの条件式が複合した時、NOTとORが条件の中にあると、どの条件式に対してNOT、ORの演算が行われるのかわかりづらくなります。特に、ORは適切な位置に( )が設定されていないと、思わぬバグになりかねません。なので、AND演算に置き換えられる部分は、できる限りANDを使用した方が後で見返した時にもわかりやすく、バグの予防になります。場合によっては、次回講座でお話しする関数というものを使用すると、もっとわかりやすく記述することができますが、それでも上記のことは意識しておくと良いです。
cast キャスト(型変換)
プログラミングでは変数等の型を変換することを、キャストといいます。ただし、キャストは数値型から文字列型や、浮動小数点型から整数型など、単純に変換が可能なもの以外では行えません。(浮動小数点は小数点以下が切り捨てられて整数に変換されます。)
Visual Studio ではエラーが発生する可能性がないキャストは暗黙的に行われ、エラーにはなりません。また、コンパイルエラーが出る場合でも明示的なキャストが修正候補として提示されている場合、キャストは可能ですが、実行時エラーが発生する可能性があります。例えば、数値同士でも最大桁数の大きい型から小さい型へのキャストを行った時に、実際の数値がキャスト先の最大桁数をオーバーしていると実行時エラーになります。このため、暗黙的に行われるものを除き、キャストを安易に使用することは避けるべきです。
今回、+演算子で説明したParseの様に特別に機能が設けられていて変換できる場合でも、本来は変換が可能か事前にチェックするか、変換できずに実行時エラーとなった場合のエラー処理を適切にする必要があります。
次回の関数についての講座では、Parseを例にして変換前のチェック、およびエラー処理についても解説します。
今回の講座は以上となります。
この記事へのコメントはありません。