C#の<<�は?複数・シフト・論理AND・論理排他的OR・論理OR演算子の優先順位とビット演算の実用性

- システム
エンジニア - C#のビット演算についてくわしく教えてください。
- プロジェクト
マネージャー - わかりました。それでは、C#のビット演算について解説いたしましょう。
C#の<<�とは?
C#で使用する<<�はビット演算に利用するものです。そもそもビット演算とは何なのでしょうか。人間は10進数を使いますが、コンピューターは実は2進数しか理解できません。10010110…のように、0と1だけの数字でしか処理できないのです。
ただしC#などのプログラム上では2進数を10進数や16進数に変換して扱っています。それなら2進数については知らなくて良いのでしょうか。決してそうではありません。
コンピュータは2進数で動作するため、2進数で計算すると処理が高速になったり、0か1のフラグを省メモリで持てると言ったメリットがあります。
<<�はビット演算で使う演算子
そういった2進数の演算をすることをビット演算と言います。そして<<�はそのビット演算をするための演算子なのです。<<�の他にも>>などがあります。この記事ではC#で演算子を使うビット演算の方法を紹介しましょう。
では早速<<�について解説します。<<�は正式な名前は左シフト演算子と言います。以下のC#サンプルをご覧ください。
uint i = 0b0001;
i = i << 1;
Console.WriteLine(i+” “+Convert.ToString(i, 2));
左シフト演算子の実例
uintとはunsigned intのことで、正の数の整数の型です。2進数ではこの型を使うとわかりやすくなります。0b0001の0bとは2進数を記述する場合のルールで、C#では先頭に0bを付けることで2進数を扱えます。
次のi = i << 1;で、iを左に1ビットシフトしています。Convert.ToString(i, 2)はiを2進数の文字列に変換します。実行すると、
2 10
と表示されます。左が10進数表記、右が2進数表記です。10進数と2進数の関係は以下のようになります。2進数は0と1しか使えないので、どんどん桁が上がっていきます。
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
<<�についての応用
<<�は以下の様に<<=という記述もできます。以下のサンプルでは左に2ビットシフトしています。
uint i = 0b0001;
i <<= 2;
Console.WriteLine(i+” “+Convert.ToString(i, 2));
実行結果は、
4 100
になります。このように<<�は2進数で桁を繰り上げる動作をします。ここで気づいた人もいると思いますが、左に1ビットシフトするのは、以下と同じです。
i *= 2;
つまり1ビット左にシフトする、とは、2を掛ける・2倍することと同じなのです。
右シフト演算子について
次は右シフト演算子の>>を解説しましょう。ここまで読んでいれば>>の動作は予想がつきますね。以下のC#サンプルをご覧ください。
uint i = 0b0100;
i >>= 1;
Console.WriteLine(i+” “+Convert.ToString(i, 2));
実行結果は、
2 10
になります。100(4)が1つ右シフトして10(2)になりました。>>=1することは/=と同じ、つまり2で割ることと同じになります。
論理AND演算子について
他のビット演算で使われる演算子も紹介します。まずは論理AND演算子です。以下のC#サンプルをご覧下さい。
uint i1 = 0b0101;
uint i2 = 0b1100;
Console.WriteLine(Convert.ToString(i1 & i2, 2));
i1とi2の間の&が論理AND演算子です。この結果は、
100
となります。つまり0100ですね。&は2進数の各桁で掛け算を行います。このサンプルの場合、上の桁から
0x1=0
1×1=1
0x0=0
1×0=0
により、0100となるのです。
論理OR演算子について
他によく使われるのは論理OR演算子です。上のC#サンプルの&を以下のように|に変えてみましょう。
uint i1 = 0b0101;
uint i2 = 0b1100;
Console.WriteLine(Convert.ToString(i1 | i2, 2));
実行結果は、
1101
になります。|は&と違い、各桁の加算を行います。ただし1と1を加算した場合は1のままです。このサンプルでは上の桁から、
0+1=1
1+1=1
0+0=0
1+0=1
と演算され、1101となりました。
論理排他的OR演算子について
論理排他的OR演算子についても紹介します。上のC#サンプルの|を^にしましょう。
uint i1 = 0b0101;
uint i2 = 0b1100;
Console.WriteLine(Convert.ToString(i1 ^ i2, 2));
実行結果は、
1001
となります。^は各桁を比較し、以下のように違う値であれば1、同じであれば0にします。
0と1 1
1と1 0
0と0 0
1と0 1
なお論理排他的OR演算子は、XOR演算子とも言われます。
補数演算子について
補数演算子の~について説明しましょう。以下のC#サンプルを実行すると、
uint i = 0b0101;
Console.WriteLine(Convert.ToString(~i, 2));
以下のようになります。
11111111111111111111111111111010
~は1なら0、0なら1のように各桁のビットを反転させる機能があります。5桁目以上が反転して1になっていますが、4桁目までは1010となって0101が反転しているのがわかりますね。
演算子の優先順位
ここまで紹介した演算子の優先順位はどうなっているのでしょうか。以下は優先度の高い順になっています。
補数演算子 ~
シフト演算子 <<�と>>
論理AND演算子 &
論理排他的OR演算子 ^
論理OR演算子 |
例えば以下の結果は、
uint i1 = 0b0100;
uint i2 = 0b0010;
Console.WriteLine(Convert.ToString(i1 & i2 << 1, 2));
100になります。i2が先に左シフトされて0100になるので、その後に&でi1と掛け算をして0100となるわけです。
C#におけるビット演算の実用性
<<�をはじめとするビット演算子について紹介しましたが、実際にどのように役に立つのでしょうか。先に述べたように演算の高速化やメモリの節約に役立ちます。しかし今のコンピュータではビット演算による高速化や節約は効果が少なく、それほど意味がありません。
昔のコンピュータはメモリが少なく、少しでも高速化やメモリを節約する必要があったので、このようなビット演算が使われていたのです。
ビットフラグの使い方
それでも敢えてC#でビットフラグを使ってみましょう。以下のサンプルをご覧ください。
uint bitflag = 0;
const uint A_FLAG = (1 << 0);
const uint B_FLAG = (1 << 1);
const uint C_FLAG = (1 << 2);
bitflag |= B_FLAG; // Bフラグを立てる
if ((bitflag & B_FLAG) != 0) Console.WriteLine(“Bフラグが立っています。”);
bitflag &= ~B_FLAG; // Bフラグを消す
if ((bitflag & B_FLAG) == 0) Console.WriteLine(“Bフラグが立っていません。”);
ビットフラグはメモリを節約できる
上のC#サンプルでは、bitflagにB_FLAGを|して0100にしています。その後、~で反転したB_FLAGを&で掛け合わせて、B_FLAGの桁を0にしています。このやり方のメリットは、1つの変数で、桁の数だけのフラグを使えることです。
ビットフラグを使わずbool型でフラグ管理をする場合、以下のように沢山の変数が必要になります。ビットフラグは変数が1つだけで済むのでスマートと言えます。
bool a_flag;
bool b_flag;
bool c_flag;
とはいえ、C#を使う環境でビットフラグを使わなければならないほどメモリが不足していることはありえないので、bool型を列挙する方法で問題はありません。実際にC#でビットフラグを使っている人はまずいないでしょう。
- システム
エンジニア - 今のコンピュータではビット演算による高速化や節約は効果が少なく、それほど意味がないということですが。
- プロジェクト
マネージャー - 確かに最近のパソコンの性能を考えれば、それほど意味はないかもしれませんが、ビット演算のことを理解していれば、コンピュータの仕組みの理解も深まります。
<<�の意味を知ればコンピュータの仕組みの理解が深まる
<<�やそれに関連するビット演算について解説しましたが、ご理解頂けましたでしょうか。C#で実際にビット演算をする機会は少ないと思いますが、知っておけばコンピュータの仕組みの理解が深まるのは確かでしょう。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
-
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅) -
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅) -
デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅) -
基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)