ビット演算子の概要
F#の整数型にのみ使用できる演算子にビット演算子というものが存在します。コンピュータは 0 と 1 のみの数値の羅列で表現(= ビットの集合体として表現)されていることはよく知られているところだと思います。ここではその "ビット" 単位で処理をするための演算子の紹介をしますが、ビットについて詳しくは解説しません。
作成するアプリケーションによっては一生この演算子と縁がない人もいるかもしれません。しかし、パフォーマンスを求めたくなったときなどにはビット演算が非常に有効に働く場面もあるので、微かにでも頭に入れておくと良いでしょう。また、ビット演算についてさらに詳しく知りたい方は、IPAが行っている基本情報技術者資格のテキストを読んでみるのもいいかもしれません。当サイトでもいつか解説したいとは思いますが、いつになるか不明なため、そちらの利用をおすすめします。
以下がビット演算子の一覧となります。
ビット演算子 | 概要 |
---|---|
~~~ (ビット単位の論理否定) | NOT演算子. これは単項演算子であり, すべての 0bit が 1bit に変換され, 1bit が 0bit に変換されます. |
||| (ビット単位の論理和) | OR演算子. 左辺と右辺の対応する bit のうちいずれか片方が 1bit の場合に 1bit となり, 両方とも 0bit の場合に 0bit となります. |
&&& (ビット単位の論理積) | AND演算子. 左辺と右辺の対応する bit のうち両方が 1bit の場合に限り 1bit となり, 片方でも 0bit の場合に 0bit となります. |
^^^ (ビット単位の排他的論理和) | XOR演算子. 左辺と右辺の対応する bit が異なる bit の場合に 1bit となり, 同じ bit の場合に 0bit となります. |
<<< (左シフト演算) | 左シフト演算子. 右辺のbit数だけ左にシフトされたビットを持つ左辺値を作成します. 1bit 左シフトした場合は 左辺値が 2倍 された値となります. |
>>> (右シフト演算) | 右シフト演算子. 右辺のbit数だけ右にシフトされたビットを持つ左辺値を作成します. 1bit 右シフトした場合は 左辺値が 1/2 された値となります. |
ビット演算に利用できる整数型は byte / sbyte / int16 / uint16 / int32(int) / uint32 / int64 / uint64 / nativeint / unativeint のみですので、注意してください。
サンプルでみるビット演算子
言葉で説明するよりも実際の動きを見ていただいたほうがイメージがつくと思いますので、以下のサンプルをご参照してください。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[<EntryPoint>] | |
let main argv = | |
// ------------------------------------------------------------- | |
// 単純な論理演算子の結果は以下のようになります. | |
// | |
printfn "0xFF= %d, ~~~0xFF= %d" 0xFF (~~~0xFF) | |
printfn "0xFF= %d, 0x80= %d, 0xFF ||| 0x80= %d" 0xFF 0x50 (0xFF ||| 0x50) | |
printfn "0xFF= %d, 0x80= %d, 0xFF &&& 0x80= %d" 0xFF 0x50 (0xFF &&& 0x50) | |
printfn "0xFF= %d, 0x80= %d, 0xFF ^^^ 0x80= %d" 0xFF 0x50 (0xFF ^^^ 0x50) | |
printfn "1 <<< 1 = %d" (1 <<< 1) | |
printfn "1 <<< 2 = %d" (1 <<< 2) | |
printfn "1 <<< 3 = %d" (1 <<< 3) | |
printfn "10 >>> 1 = %d" (10 >>> 1) | |
printfn "10 >>> 2 = %d" (10 >>> 2) | |
printfn "10 >>> 3 = %d" (10 >>> 3) | |
// | |
// 0xFF = 0b1111_1111 | |
// 0x50 = 0b0101_0000 | |
// | |
// output: | |
// 0xFF= 255, ~~~0xFF= -256 ~~~0xFF= 0b0000_0000 | |
// | |
// ◎ 対応する各ビットのうち片方でも 1bit なら 1bit になる. | |
// 0xFF= 255, 0x50= 80, 0xFF ||| 0x50= 255 0xFF : 0b1111_1111 | |
// ||| 0x50 : 0b0101_0000 | |
// ----------------------- | |
// 0xFF : 0b1111_1111 | |
// | |
// ◎ 対応する各ビットが両方 1bit の場合のみ 1bit になる. | |
// 0xFF= 255, 0x50= 80, 0xFF &&& 0x50= 80 0xFF : 0b1111_1111 | |
// &&& 0x50 : 0b0101_0000 | |
// ----------------------- | |
// 0x50 : 0b0101_0000 | |
// | |
// ◎ 対応する各ビットが異なる場合に 1bit となる. | |
// 0xFF= 255, 0x50= 80, 0xFF ^^^ 0x50= 175 0xFF : 0b1111_1111 | |
// ^^^ 0x50 : 0b0101_0000 | |
// ----------------------- | |
// 0xAF : 0b1010_1111 | |
// | |
// ◎ 1 = 0b0001 | |
// 1 <<< 1 = 2 // 1 の 2倍 0b0010 | |
// 1 <<< 2 = 4 // 1 の 4倍 0b0100 | |
// 1 <<< 3 = 8 // 1 の 8倍 0b1000 | |
// | |
// ◎ 10 = 0b1010 | |
// 10 >>> 1 = 5 // 10 の 1/2 0b0101 | |
// 10 >>> 2 = 2 // 10 の 1/4 0b0010 | |
// 10 >>> 3 = 1 // 10 の 1/8 0b0001 | |
// | |
0 | |