C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com
今回は 「 ジェネリック型数値演算のサポート - 符号なし右シフト演算子 」。公式 Learn の記事は次です。
learn.microsoft.com
新しい右シフト演算子 >>>
ができました。
■ 確認
int i= -1 >>> 1;
ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。
エラー CS8936 機能 '符号なし右シフト' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
■ 実行
実行結果は次のようになります。
int i= -1 >>> 1; Console.WriteLine(Convert.ToString(i, toBase: 2).PadLeft(32, '0')); // 01111111111111111111111111111111
■ 右シフト演算
これは結構マニアックな仕様なので、丁寧に基本のシフト演算から確認して行きましょう。
正の数をシフト演算
まずは正の数をシフト演算してみます。11
の位置が左右に移動 (シフト) しているのが分かります。
Console.WriteLine(Convert.ToString(3, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(3 << 1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(3 >> 1, toBase: 2).PadLeft(32, '0')); // 00000000000000000000000000000011 // 00000000000000000000000000000110 // 00000000000000000000000000000001
負の数をシフト演算
負の数をシフト演算すると不思議な感じに。左にシフトしたときには、右端に 0
が埋まったのに、右にシフトしたときには左端が 1
で埋まっています。
Console.WriteLine(Convert.ToString(-1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(-1 << 1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(-1 >> 1, toBase: 2).PadLeft(32, '0')); // 11111111111111111111111111111111 // 11111111111111111111111111111110 // 11111111111111111111111111111111
ビットでなく、数値としてみると分かりやすいかもしれません。
Console.WriteLine(4 << 1); Console.WriteLine(4 >> 1); Console.WriteLine(-4 << 1); Console.WriteLine(-4 >> 1); // 8 // 2 // -8 // -2
■ 普通に 1
の位置がシフトして欲しい
そんな時に今回追加された >>>
です。
Console.WriteLine(Convert.ToString(-1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(-1 << 1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString(-1 >>> 1, toBase: 2).PadLeft(32, '0')); // 11111111111111111111111111111111 // 11111111111111111111111111111110 // 01111111111111111111111111111111
■ これまではこうしていた
これまでは次のように uint にしていたようです。今回の >>>
で便利になりましたね!
unchecked { Console.WriteLine(Convert.ToString((uint)-1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString((uint)-1 << 1, toBase: 2).PadLeft(32, '0')); Console.WriteLine(Convert.ToString((uint)-1 >> 1, toBase: 2).PadLeft(32, '0')); } // 11111111111111111111111111111111 // 11111111111111111111111111111110 // 01111111111111111111111111111111
■ 覚えておきましょう
この機能は使わない人はほとんど使わない機能かもしれません。しかし >>>
という演算子は非常に Web 検索が難しいのではないかと思います。出会ったときに検索しなくて済むように覚えておきましょう。