前一篇只能操作單位元,這裡補充說明多位元操作,原理是把不同位置的旗標先OR起來即可,另外也能練習C#的"|="與"params"語法
單元測試
Convert.ToString(10,2).PadLeft(8,'0')
"00001010"
Convert.ToString(0b_0000_1010,2).PadLeft(8,'0')
"00001010"
BitOperator.CheckBits(0b_0000_1010, 3, 2, 1)
false
BitOperator.CheckBits(0b_0000_1010, 3, 1)
true
BitOperator.CheckBits(0b_0000_1010, 5, 3, 1)
false
BitOperator.CheckBits(0b_0000_1010, 5)
false
BitOperator.CheckBits(0b_0000_1010, 3)
true
Convert.ToString(BitOperator.GetBits(0b_0000_1010,3,2,1),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.GetBits(0b_0000_1010,3,1),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.GetBits(0b_0000_1010,5,3),2).PadLeft(8,'0')
"00001000"
Convert.ToString(BitOperator.GetBits(0b_0000_1010,5),2).PadLeft(8,'0')
"00000000"
Convert.ToString(BitOperator.GetBits(0b_0000_1010,3),2).PadLeft(8,'0')
"00001000"
Convert.ToString(BitOperator.AddBits(0b_0000_1010,7),2).PadLeft(8,'0')
"10001010"
Convert.ToString(BitOperator.AddBits(0b_0000_1010,7,5),2).PadLeft(8,'0')
"10101010"
Convert.ToString(BitOperator.AddBits(0b_0000_1010,7,3),2).PadLeft(8,'0')
"10001010"
Convert.ToString(BitOperator.AddBits(0b_0000_1010,7,3,2,1),2).PadLeft(8,'0')
"10001110"
Convert.ToString(BitOperator.RemoveBits(0b_0000_1010,7),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.RemoveBits(0b_0000_1010,7,5),2).PadLeft(8,'0')
"00001010"
Convert.ToString(BitOperator.RemoveBits(0b_0000_1010,7,3),2).PadLeft(8,'0')
"00000010"
Convert.ToString(BitOperator.RemoveBits(0b_0000_1010,7,3,2,1),2).PadLeft(8,'0')
"00000000"
單元測試正常
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 bool CheckBits(in byte value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return (value & bits) == bits;
}
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 GetBits(in byte value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return (byte)(value & bits);
}
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 AddBits(in byte value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return (byte)(value | bits);
}
public static byte RemoveBit(in byte value, in int position)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
//return CheckBit(value, position) ? (byte)(value - BitValue[position]) : value;
return (byte)(value & ~BitValue[position]);
}
public static byte RemoveBits(in byte value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(byte) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return (byte)(value & ~bits);
}
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 bool CheckBits(in uint value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return (value & bits) == bits;
}
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 GetBits(in uint value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return value & bits;
}
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 AddBits(in uint value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return value | bits;
}
public static uint RemoveBit(in uint value, in int position)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
//return CheckBit(value, position) ? value - BitValue[position] : value;
return value & ~BitValue[position];
}
public static uint RemoveBits(in uint value, params int[] positions)
{
if (positions == null || positions.Length <= 0)
{
throw new ArgumentException($"{nameof(positions)} == null || {nameof(positions)}.Length <= 0");
}
uint bits = 0;
foreach (int position in positions)
{
if (position < 0 || position >= sizeof(uint) * 8)
{
throw new IndexOutOfRangeException($"{nameof(position)}={position}");
}
bits |= BitValue[position];
}
return value & ~bits;
}
}