++C++; // 未確認飛行 C 避けて通れない「非同期処理」を克服しよう

Top総合 目次C# によるプログラミング入門

組込み演算子

このエントリーをはてなブックマークに追加

目次

キーワード

概要

+、-、×、÷のように、 いくつかの変数に対して何らかの処理を加えるもののことを演算子(operator)と呼びます。 また、演算の対象となるもの(x+y の x や y)のことをオペランド(operand: 被演算子)と呼びます。

-x のように、1つのオペランドを必要とする演算子のことを単項演算子(unary operator)、 x+y のように、2つのオペランドを必要とする演算子のことを2項演算子(binary operator)と呼びます。 また、2項演算において、 演算子の左側にあるオペランドのことを左オペランド(left hand side operand)、 演算子の右側にあるオペランドのことを右オペランド(right hand side operand)といいます。

C# では、算術演算や論理演算を行うための演算子が用意されています。

ポイント
  • 演算子: 加減乗除など、数学で出てくるような演算子がいろいろと。
  • x = y は、数学と違って代入なので注意。
    • 数学の場合: 「x は y と等しい」あるいは「x と y が等しくなるように値を決める」。
    • プログラミングの場合: 「x に y を代入する」あるいは「y の値を改めて x と書く」。

ちなみに、いくつかの演算子は、組み込み型に対するものだけでなく、 後述するクラスや構造体などのユーザー定義型では自作することができます。 (参考: 「演算子のオーバーロード」 。)

算術演算子

+, -, *, / を用いて加減乗除算を行えます。 また、+, - を用いて数値の符号を反転することが出来ます。

整数型の除算は余り切り捨てとなります。剰余を求めたい場合は % 演算子を用います。

これらの算術演算子はすべての数値型に対して利用できます。

演算子意味
x + y x と y を足す byte a = 11 + 92; // a は 103 になる。
x - y x から y を引く int a = 9 - 4; // a は 5 になる。
x * y x と y を掛ける int a = 3 * 7; // a は 21 になる。
x / y x を y で割る int a = 9 / 2; // 整数の場合、あまり切り捨て。 a は 4 になる。
double x = 9.0 / 2.0; // a は 4.5 になる。
x % y x を y で割った余り int a = 9 % 2; // a は 1 になる。
+x x の値そのまま int a = +1; // a = 1 と同じ
-x 符号反転 int a = 1;
int b = -a; // b は -1 になる。

注意1: 整数の除算 x / y は、0 に向かって丸められます。 すなわち、x / y の結果が正の場合は切捨て、 負の場合は切上げになります。

注意2: 剰余演算 x % y は、 整数の場合は x - (x / y) * y、 浮動小数点数の場合は x - Math.Floor(x / y) * y と同じ値になります。

インクリメント・デクリメント

++, -- を用いてインクリメント、デクリメント演算を行うことが出来ます。 インクリメント演算を行うとオペランドは 1 ずつ増加(++xx = x + 1 と同じ)し、 デクリメント演算を行うとオペランドは 1 ずつ減少(--xx = x - 1 と同じ)します。

インクリメント・デクリメント演算には前置き(++xという形式)と後置き(x++という形式)があります。 前置き演算の演算結果は、インクリメント・デクリメントが行われた後のオペランドの値になり、 後置き演算の演算結果は、インクリメント・デクリメントが行われる前のオペランドの値になります。

これらの算術演算子はすべての数値型に対して利用できます。

演算子意味
++x 前置きインクリメント int a = 5;
int b = ++a; // a も b も 6 になる。
x++ 後置きインクリメント int a = 5;
int b = a++; // a は 6 に、b は 5 になる。
--x 前置きデクリメント int a = 5;
int b = --a; // a も b も 4 になる。
x-- 後置きデクリメント int a = 5;
int b = a--; // a は 4 に、b は 5 になる。

シフト

<< は左シフトを、 >> は右シフトを行う演算子です。

シフト演算子は左側のオペランドを右側のオペランド分だけ左または右にシフトします。 左オペランドには int, uint, long, ulong のみを、 右オペランドには int のみを取ることが出来ます。

左オペランドが符号付き整数の場合、右シフトは算術シフト演算になり、 符号無し整数の場合、右シフトは論理シフト演算になります。

演算子意味
x<<i 左シフト int a = 51 << 2 ; // a は 204 になる。
(0011 0011 << 2 = 1100 1100)
x>>i 右シフト int a = 51 >> 1 ; // a は 25 になる。
(0011 0011 >> 1 = 0001 1001)

文字列連結

文字列に対して + 演算子を用いることで文字列の連結を行えます。

演算子意味
x+y 文字列連結 string s = "abc" + "def"; // s は "abcdef" になる。

論理演算子

AND, OR, XOR などの論理演算を行います。

&, |, ^ はそれぞれ AND, OR, XOR を行う演算子です。 これらの演算子は整数型および bool 型に対して利用できます。 整数型に対してこれらの演算子を用いた場合、ビットごとの論理演算を行います。

! は論理否定を行う演算子です。 この演算子は bool 型に対してのみ利用できます。

~ はビットごとの補数演算(各ビットの 0/1 を反転する)を行う演算子です。 この演算子は int, uint, long, ulong に対してのみ利用できます。

&&, || は条件 AND, OR 演算子で、 その演算結果は bool に対する &, | の演算結果と同じものになります。 &, | の演算との違いは、後述する短絡評価を行うかどうかです。 この短絡評価版の論理演算子は bool 型に対してのみ利用できます。

演算子意味
x & y x と y の論理積を計算 byte a = true & false; // a は false になる。
byte a = 201 & 92; // a は 72になる。
(1100 1001 AND 0101 1100 = 0100 1000)
x | y x と y の論理和を計算 byte a = true | false; // a は true になる。
byte a = 201 | 92; // a は 221になる。
(1100 1001 OR 0101 1100 = 1101 1101)
x ^ y x と y の排他的論理和を計算 byte a = true ^ true; // a は falseになる。
byte a = 201 ^ 92; // a は 149になる。
(1100 1001 XOR 0101 1100 = 1001 0101)
!x x の論理否定を計算 bool a = !true; // a は false になる。
~x x の補数を計算 int a = ~201; // a は -202 になる。
~(0000 0000 1100 1001) = 1111 1111 0011 0110

関係演算

==, != を用いてオペランドの等値性を判断できます。 == は2つのオペランドが等しければ true を、 != は2つのオペランドが等しくなければ true を返します。 これらの演算子はすべての組込み型に対して利用でき、 数値型の場合はその値の比較、文字列型の場合はすべての文字が一致しているかどうか、 オブジェクト型の場合はオブジェクトの参照先が同じかどうかを調べます。

<, >, <=, >= はオペランドの大小比較を行います。 これらの演算子は数値型に対して利用できます。

演算子意味
x == y x が y と等しいかどうか bool a = "abc" == "abc"; // a は true になる。
bool a = 1 == 0; // a は false になる。
x != y x が y と異なるかどうか bool a = "abc" != "abc"; // a は false になる。
bool a = 1 != 0; // a は true になる。
x < y x が y より小さいかどうか bool a = 1 < 2; // a は true になる。
bool a = 1 < 1; // a は false になる。
bool a = 1 < 0; // a は false になる。
x > y x が y より大さいかどうか bool a = 1 > 2; // a は false になる。
bool a = 1 > 1; // a は false になる。
bool a = 1 > 0; // a は true になる。
x <= y x が y 以下かどうか bool a = 1 <= 2; // a は true になる。
bool a = 1 <= 1; // a は true になる。
bool a = 1 <= 0; // a は false になる。
x >= y x が y 以上かどうか bool a = 1 >= 2; // a は false になる。
bool a = 1 >= 1; // a は true になる。
bool a = 1 >= 0; // a は true になる。

代入演算

=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= を用いて代入を行えます。

= では、右オペランドの値を左オペランドに代入します。

( 数学の場合、= は比較演算(C# の場合、== 演算子を使う)ですが、 C# では代入になります。 )

a += b;a = a + b; と同じ意味になります。 -=, *=, /=, %=, &=, |=, ^=, <<=, >>= も同様です。

これらの演算子はすべての型に対して用いることが出来ますが、 左右のオペランドの型は一致している必要があります。

演算子意味
x = y x に y を代入します int a = 5; // a は 5 になる。
x += y x = x + y と同じ結果が得られる int a = 5;
a += 10; // a は 15 になる。

条件演算子

?: 演算子、は C# における唯一の3項演算子(trinary operator: オペランドが3つの演算子)で、 1つ目のオペランドの結果に応じて2つ目か3つ目のどちらかのオペランドの値を返します。 例えば、cond ? x : y;condtrue ならば x を、 condfalse ならば y を返します。

1つ目のオペランドは bool 型でなければなりません。 また、2つ目と3つ目のオペランドにはすべての型を利用できますが、 両方が同じ型である必要があります。

演算子意味
c ? x : y c が true ならば x を、
false ならば y を返します
int a = (x > 5) ? 10 : 0;
// a は、x が 5 より大きければ 10 に、
// さもなくば 0 になります。

null 合体演算子

Ver. 2.0

無効な値(null)を許容する型(参照型 もしくは Nullable 型)に対して、 「値が無効な時、デフォルト値を代入しなおしたい」ということが多々あります。 すなわち、以下のような条件演算を結構よく利用します。

string str = null;

string nonNullStr = str != null ? str : "default string";

そこで、C# 2.0 では、この条件演算に相当する処理を簡潔に書くために、null 合体演算子(null coalescing operator) ?? というものが導入されました。 上記の例は、以下の書くことができます。

string str = null;

string nonNullStr = str ?? "default string";

sizeof 演算子

sizeof 演算子は、他の演算子と比べると少し特殊で、 以下のように、型に対して用います。

Console.Write("{0}, {1}\n", sizeof(int), sizeof(byte));
4, 1

sizeof 演算子は、その型が何バイトのメモリを占めるかを返します。 int(32ビット整数)なら4バイト、 byte(8ビット符号なし整数)なら1バイトなので、 sizeof(int), sizeof(byte) はそれぞれ 4, 1 を返します。

通常、sizeof 演算子の引数として与えられる型は、int や byte など、C# の規格上、サイズが決まっている数値型のみです。 (unsafe コードと呼ばれる特殊な状況下でのみ、もう少し広い範囲の型のサイズを取得できます。参考: 「unsafe」 。)

短絡評価

条件 AND &&、 条件 OR ||、 条件演算子 ?:、および、null 合体演算子 ??短絡評価(short circuit evaluation)と呼ばれる挙動をします。

短絡評価は、左辺の結果によっては右辺が評価されない(関数などを呼ぼうとしても呼ばれない)というものです。

演算子挙動
条件 AND && 左オペランドが false の場合、右オペランドは評価されません。
条件 OR || 左オペランドが true の場合、右オペランドは評価されません。
条件演算子 ?: 第1項が true なら第2項のみ、 false なら第3項のみが評価されます。
null 合体演算子 ?? 左オペランドが false の場合、右オペランドは評価されません。

例えば、| 演算子と || 演算子の挙動の差を見てみましょう。

using System;

class Program
{
    static string Echo(string message)
    {
        Console.WriteLine(message);
        return message;
    }

    static void Main()
    {
        Console.WriteLine("短絡評価なし");
        var x = Echo("a") == "a" | Echo("b") == "b"; // a、b 両方出力。

        Console.WriteLine("短絡評価あり");
        var y = Echo("a") == "a" || Echo("b") == "b"; // a のみ出力
    }
}
短絡評価なし
a
b
短絡評価あり
a

また、条件演算子の短絡評価の例を示すと、以下のようになります。

using System;

class Program
{
    static string Echo(string message)
    {
        Console.WriteLine(message);
        return message;
    }

    static void Main()
    {
        var x = true ? Echo("第2項") : Echo("第3項"); // 第2項だけ表示される
        var y = false ? Echo("第2項") : Echo("第3項"); // 第3項だけ表示される
    }
}
第2項
第3項

その他の式

このページで紹介したような、数学でも出てくるような演算子は、 C# の構文上は式(expression)と呼ばれるものの一種です。 式には、その他にもいろいろな種類のものがあり、おいおい説明してくことになります。 (参考: 「C# の式と文の一覧」 )

演算子の優先順位

演算子には以下に示す優先順位があります。

分類式/演算子
基本式 x++, x--
単項式 +, -, !, ~, ++x, --x
乗法式 *, /, %
加法式 +, -
シフト <<, >>
関係式 <, >, <=, >=
等値式 ==, !=
論理 AND &
論理 XOR ^
論理 OR |
条件 AND &&
条件 OR ||
条件 ?:
null 合体 ??
代入 =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=

優先順位の高いものから順番に計算が行われます。 また、優先順位が同じ場合、代入演算では右から、それ以外の演算では左から順に計算が行われます。

他の式も含めた全体の優先順位は 「C# の式と文の一覧」 を参照ください。

演習問題

問題 1

2つの整数を入力し、 その整数の四則演算(+, -, ×, ÷)結果を表示するプログラムを作成せよ。

解答

問題 2

前問の「整数の四則演算」の、 double, short 等の他の型を用いた物を作成せよ。

解答

問題 3

複素数 x + iy の逆数を求めるプログラムを作成せよ。

解答

問題 4

半径を入力し、その半径の円の面積を求めるプログラムを作成せよ。

解答

問題 5

体重と身長を入力し、BMIを求めるプログラムを作成せよ。

BMIは、WHO(世界保健機関)が推奨しているもので、Body Mass Indexの略称で、肥満度指数とも呼ばれています。 BMIは肥満度の基準として、広く使用されている測定方法です。 計算式は、下記のとおりで比較的簡単に計算できることも特徴です。

BMI = 体重(kg)÷{身長(m)×身長(m)}

BMIの値が22のときに病気になる可能性が最も低く、BMIが26を超えると糖尿病など生活習慣病になるリスクが高まると言われています。

BMI 値
19.8未満やせ型
19.8~24.2未満普通
24.2~26.4未満やや肥満(過体重)
26.4~35.0未満肥満
35.0以上高度肥満(要治療)

以下にプログラムの実行結果の例を示す。

身長[cm] = 175.5
体重[kg] = 52.4
BMI = 17.0128489216808

解答

[お問い合わせ](q)