移位運算(>> / <<),邏輯運算(AND / OR)(& / |),位元補充(~),2進制數值表示(0b),16進制數值表示(0x),相關功能包裝與使用範例紀錄於此
Byte內的位元位置通常從0開始,代稱為:
Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 |
CheckBit,檢查指定的位元其值是否不為0
GetBit,取出指定的位元值,屏蔽其他位元值
AddBit,指定的位元其值設定為1
RemoveBit,指定的位元其值設定為0
public class BitOperator
{
public static readonly uint[] BitValue = {
(uint)Math.Pow(2, 0),
(uint)Math.Pow(2, 1),
(uint)Math.Pow(2, 2),
(uint)Math.Pow(2, 3),
(uint)Math.Pow(2, 4),
(uint)Math.Pow(2, 5),
(uint)Math.Pow(2, 6),
(uint)Math.Pow(2, 7),
(uint)Math.Pow(2, 8),
(uint)Math.Pow(2, 9),
(uint)Math.Pow(2, 10),
(uint)Math.Pow(2, 11),
(uint)Math.Pow(2, 12),
(uint)Math.Pow(2, 13),
(uint)Math.Pow(2, 14),
(uint)Math.Pow(2, 15),
(uint)Math.Pow(2, 16),
(uint)Math.Pow(2, 17),
(uint)Math.Pow(2, 18),
(uint)Math.Pow(2, 19),
(uint)Math.Pow(2, 20),
(uint)Math.Pow(2, 21),
(uint)Math.Pow(2, 22),
(uint)Math.Pow(2, 23),
(uint)Math.Pow(2, 24),
(uint)Math.Pow(2, 25),
(uint)Math.Pow(2, 26),
(uint)Math.Pow(2, 27),
(uint)Math.Pow(2, 28),
(uint)Math.Pow(2, 29),
(uint)Math.Pow(2, 30),
(uint)Math.Pow(2, 31),
};
public static bool CheckBit(in byte value, in int position)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return (value & BitValue[position]) > 0;
}
public static byte GetBit(in byte value, in int position)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return (byte)(value & BitValue[position]);
}
public static byte AddBit(in byte value, in int position)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return (byte)(value | BitValue[position]);
}
public static byte RemoveBit(in byte value, in int position)
{
//return CheckBit(value, position) ? (byte)(value - BitValue[position]) : value;
return (byte)(value & ~BitValue[position]);
}
public static bool CheckBit(in uint value, in int position)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return (value & BitValue[position]) > 0;
}
public static uint GetBit(in uint value, in int position)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return value & BitValue[position];
}
public static uint AddBit(in uint value, in int position)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
return value | BitValue[position];
}
public static uint RemoveBit(in uint value, in int position)
{
//return CheckBit(value, position) ? value - BitValue[position] : value;
return value & ~BitValue[position];
}
}
單元測試與註解說明:
Convert.ToString(10,2).PadLeft(8,'0')
"00001010"
Convert.ToString(0b_0000_1010,2).PadLeft(8,'0')
"00001010"
Convert.ToString(0b_0000_1010 >> 1,2).PadLeft(8,'0')
"00000101"
Convert.ToString(0b_0000_1010 << 1,2).PadLeft(8,'0')
"00010100"
Convert.ToString(0b_0000_1010 >> 3,2).PadLeft(8,'0')
"00000001"
Convert.ToString(0b_0000_1010 >> 4,2).PadLeft(8,'0')
"00000000"
Convert.ToString(0b_0000_1010 >> 5,2).PadLeft(8,'0')
"00000000"
Convert.ToString(0b_0000_1010 << 3,2).PadLeft(8,'0')
"01010000"
Convert.ToString(0b_0000_1010 << 4,2).PadLeft(8,'0')
"10100000"
//移位運算的回傳值型態看來預設是int
Convert.ToString(0b_0000_1010 << 5,2).PadLeft(8,'0')
"101000000"
Convert.ToString((byte)0b_0000_1010 << 5,2).PadLeft(8,'0')
"101000000"
Convert.ToString(0b_0000_1010 << (byte)5,2).PadLeft(8,'0')
"101000000"
Convert.ToString((byte)(0b_0000_1010 << 5),2).PadLeft(8,'0')
"01000000"
Convert.ToString((byte)(0b_0000_1010 << 6),2).PadLeft(8,'0')
"10000000"
Convert.ToString((byte)(0b_0000_1010 << 7),2).PadLeft(8,'0')
"00000000"
Convert.ToString((byte)(0b_0000_1010 << 8),2).PadLeft(8,'0')
"00000000"
BitOperator.CheckBit(0b_0000_1010, 4)
false
BitOperator.CheckBit(0b_0000_1010, 3)
true
BitOperator.CheckBit(0b_0000_1010, 2)
false
BitOperator.CheckBit(0b_0000_1010, 1)
true
BitOperator.CheckBit(0b_0000_1010, 0)
false
//16進制數值型態是uint
Convert.ToString(0xF0000000,2)
"11110000000000000000000000000000"
BitOperator.CheckBit(0xF0000000, 31)
true
BitOperator.CheckBit(0xF0000000, 30)
true
BitOperator.CheckBit(0xF0000000, 29)
true
BitOperator.CheckBit(0xF0000000, 28)
true
BitOperator.CheckBit(0xF0000000, 27)
false
BitOperator.CheckBit(0xF0000000, 26)
false
BitOperator.GetBit(0b_0000_1010, 4)
0
BitOperator.GetBit(0b_0000_1010, 3)
8
BitOperator.GetBit(0b_0000_1010, 2)
0
BitOperator.GetBit(0b_0000_1010, 1)
2
BitOperator.GetBit(0b_0000_1010, 0)
0
BitOperator.GetBit(0xF0000000, 31)
2147483648
BitOperator.GetBit(0xF0000000, 30)
1073741824
BitOperator.GetBit(0xF0000000, 29)
536870912
BitOperator.GetBit(0xF0000000, 28)
268435456
BitOperator.GetBit(0xF0000000, 27)
0
Convert.ToString(BitOperator.AddBit(0b_0000_1010, 7),2).PadLeft(8,'0')
"10001010"
Convert.ToString(BitOperator.AddBit(0b_1000_1010, 7),2).PadLeft(8,'0')
"10001010"
Convert.ToString(BitOperator.RemoveBit(0b_0000_1010, 7),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.RemoveBit(0b_1000_1010, 7),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.AddBit(BitOperator.AddBit(0b_0000_1010, 4),3),2).PadLeft(8,'0')
"00011010"
Convert.ToString(BitOperator.AddBit(BitOperator.AddBit(0b_0001_1010, 4),3),2).PadLeft(8,'0')
"00011010"
Convert.ToString(BitOperator.RemoveBit(BitOperator.RemoveBit(0b_0000_1010, 4),3),2).PadLeft(8,'0')
"00000010"
Convert.ToString(BitOperator.RemoveBit(BitOperator.RemoveBit(0b_0001_1010, 4),3),2).PadLeft(8,'0')
"00000010"
單元測試正常
位元操作常見於資料壓縮與資料加密領域,另外在自定義的資料格式中,還能利用沒用到的位元位置偷塞其他密文,譬如定義00000000代表false,00000001代表true,就有7個bits能再設計其他用途,別浪費
位元操作也能實現簡單的對稱式金鑰加密,為資料做加鹽處理(salt),這部分範例稍後補上