我正在使用UInt64
来存储位。一个示例为UInt64 val = 0b0001_0000
。现在,我希望能够确定是否在特定位置设置了位。例如,我想知道在val
中是否设置了第4位(使用从零开始的索引)。如果要对此进行硬编码,则可以使用AND和OR运算符对一个临时变量进行操作,清除除第4个位以外的所有位并检查该值。但是,我想实现一种更动态的方法来执行此操作,因此不需要使用诸如0b0001_0000
之类的一堆不同的位文字来进行检查。
我尝试解析动态创建的类似"0b0001_0000"
的字符串,但是我对UInt64
,Byte
等并不满意。
答案 0 :(得分:0)
对于所有int,long,uint,ulong等,您都可以使用Left(<<)或Right(>>)运算符将位导航到更大的数值。
请参阅MSDN文档上的本文:Left Shift Operator和Right Shift Operator
就像这样(我从“左移运算符”页面获取了示例):
class MainClass
{
static void Main()
{
int i = 1;
long lg = 1;
// Shift i one bit to the left. The result is 2.
Console.WriteLine("0x{0:x}", i << 1);
// In binary, 33 is 100001. Because the value of the five low-order
// bits is 1, the result of the shift is again 2.
Console.WriteLine("0x{0:x}", i << 33);
// Because the type of lg is long, the shift is the value of the six
// low-order bits. In this example, the shift is 33, and the value of
// lg is shifted 33 bits to the left.
// In binary: 10 0000 0000 0000 0000 0000 0000 0000 0000
// In hexadecimal: 2 0 0 0 0 0 0 0 0
Console.WriteLine("0x{0:x}", lg << 33);
}
}
/*
Output:
0x2
0x2
0x200000000
*/
更新:
更好的是,从此站点Bit Processing in C看到完整的实现(基于BYTE结构-只需将其更改为LONG或ULONG):
更新2 :
我最终享受了Bit Processing in C文章,并实现了它的类(基于字节),并做了一些改进,使其变成了具有许多方法和接口的类。去吧:
namespace System
{
public class BitCheck8 : global::System.IEquatable<byte>, global::System.IEquatable<global::System.BitCheck8>, global::System.Collections.Generic.IEnumerable<bool>, global::System.Collections.Generic.IDictionary<int, bool>
{
public const byte Empty = 0x0;
protected byte Control;
protected static global::System.ArgumentOutOfRangeException OutOfRange() { return new global::System.ArgumentOutOfRangeException("pos", "Argument [Pos] not between 0-7"); }
public static bool IsBitSet(byte b, int pos) { if (pos < 0 || pos > 7) { throw global::System.BitCheck8.OutOfRange(); } else { return (b & (1 << pos)) != 0; } }
public static byte SetBit(byte b, int pos) { if (pos < 0 || pos > 7) { throw global::System.BitCheck8.OutOfRange(); } else { return (byte)(b | (1 << pos)); } }
public static byte UnsetBit(byte b, int pos) { if (pos < 0 || pos > 7) { throw global::System.BitCheck8.OutOfRange(); } else { return (byte)(b & ~(1 << pos)); } }
public static byte ToggleBit(byte b, int pos) { if (pos < 0 || pos > 7) { throw global::System.BitCheck8.OutOfRange(); } else { return (byte)(b ^ (1 << pos)); } }
public static string ToBinaryString(byte b) { return global::System.Convert.ToString(b, 2).PadLeft(8, '0'); }
public virtual bool IsReadOnly { get { return false; } }
public byte Base { get { return this.Control; } set { if (!this.IsReadOnly) { this.Control = value; } } }
public bool IsBitSet(int pos) { return global::System.BitCheck8.IsBitSet(this.Control, pos); }
public void SetBit(int pos) { if (!this.IsReadOnly) { this.Control = global::System.BitCheck8.SetBit(this.Control, pos); } }
public void UnsetBit(int pos) { if (!this.IsReadOnly) { this.Control = global::System.BitCheck8.UnsetBit(this.Control, pos); } }
public void ToggleBit(int pos) { if (!this.IsReadOnly) { this.Control = global::System.BitCheck8.ToggleBit(this.Control, pos); } }
public void Clear() { if (!this.IsReadOnly) { this.Control = global::System.BitCheck8.Empty; } }
public override string ToString() { return global::System.BitCheck8.ToBinaryString(this.Control); }
public bool this[int pos] { get { return this.IsBitSet(pos); } set { if (value) { this.SetBit(pos); } else { this.UnsetBit(pos); } } }
public bool Check0 { get { return this[0]; } set { this[0] = value; } }
public bool Check1 { get { return this[1]; } set { this[1] = value; } }
public bool Check2 { get { return this[2]; } set { this[2] = value; } }
public bool Check3 { get { return this[3]; } set { this[3] = value; } }
public bool Check4 { get { return this[4]; } set { this[4] = value; } }
public bool Check5 { get { return this[5]; } set { this[5] = value; } }
public bool Check6 { get { return this[6]; } set { this[6] = value; } }
public bool Check7 { get { return this[7]; } set { this[7] = value; } }
public global::System.Collections.Generic.IEnumerator<bool> GetEnumerator() { for (int pos = 0; pos < 8; pos++) { yield return this.IsBitSet(pos); } }
global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
bool global::System.IEquatable<byte>.Equals(byte b) { return this.Control == b; }
public override bool Equals(object obj) { return base.Equals(obj); }
public bool Equals(global::System.BitCheck8 obj) { return base.Equals(obj); }
public override int GetHashCode() { return base.GetHashCode(); }
void global::System.Collections.Generic.ICollection<global::System.Collections.Generic.KeyValuePair<int, bool>>.Add(global::System.Collections.Generic.KeyValuePair<int, bool> item) { this[item.Key] = item.Value; }
bool global::System.Collections.Generic.ICollection<global::System.Collections.Generic.KeyValuePair<int, bool>>.Contains(global::System.Collections.Generic.KeyValuePair<int, bool> item) { return this[item.Key]; }
int global::System.Collections.Generic.ICollection<global::System.Collections.Generic.KeyValuePair<int, bool>>.Count { get { return 8; } }
bool global::System.Collections.Generic.ICollection<global::System.Collections.Generic.KeyValuePair<int, bool>>.Remove(global::System.Collections.Generic.KeyValuePair<int, bool> item) { return false; }
void global::System.Collections.Generic.IDictionary<int, bool>.Add(int Key, bool Value) { this[Key] = Value; }
bool global::System.Collections.Generic.IDictionary<int, bool>.ContainsKey(int Key) { return (Key > -1 && Key < 8); }
bool global::System.Collections.Generic.IDictionary<int, bool>.Remove(int Key) { return false; }
global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<int, bool>> global::System.Collections.Generic.IEnumerable<global::System.Collections.Generic.KeyValuePair<int, bool>>.GetEnumerator() { for (int pos = 0; pos < 8; pos++) { yield return new global::System.Collections.Generic.KeyValuePair<int, bool>(pos, this[pos]); } }
void global::System.Collections.Generic.ICollection<global::System.Collections.Generic.KeyValuePair<int, bool>>.CopyTo(global::System.Collections.Generic.KeyValuePair<int, bool>[] array, int index) { global::System.Array.Copy(new global::System.Collections.Generic.KeyValuePair<int, bool>[] { new global::System.Collections.Generic.KeyValuePair<int, bool>(0, this[0]), new global::System.Collections.Generic.KeyValuePair<int, bool>(1, this[1]), new global::System.Collections.Generic.KeyValuePair<int, bool>(2, this[2]), new global::System.Collections.Generic.KeyValuePair<int, bool>(3, this[3]), new global::System.Collections.Generic.KeyValuePair<int, bool>(4, this[4]), new global::System.Collections.Generic.KeyValuePair<int, bool>(5, this[5]), new global::System.Collections.Generic.KeyValuePair<int, bool>(6, this[6]), new global::System.Collections.Generic.KeyValuePair<int, bool>(7, this[7]) }, 0, array, index, 8); }
global::System.Collections.Generic.ICollection<int> global::System.Collections.Generic.IDictionary<int, bool>.Keys { get { return (global::System.Collections.Generic.ICollection<int>)new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }; } }
global::System.Collections.Generic.ICollection<bool> global::System.Collections.Generic.IDictionary<int, bool>.Values { get { return (global::System.Collections.Generic.ICollection<bool>)new bool[] { this[0], this[1], this[2], this[3], this[4], this[5], this[6], this[7] }; } }
public static bool operator ==(global::System.BitCheck8 obj1, global::System.BitCheck8 obj2) { return (obj1 != null && obj2 != null && obj1.Control == obj2.Control); }
public static bool operator !=(global::System.BitCheck8 obj1, global::System.BitCheck8 obj2) { return (obj1 == null || obj2 == null || obj1.Control != obj2.Control); }
public static bool operator ==(global::System.BitCheck8 obj1, byte obj2) { return (obj1 != null && obj1.Control == obj2); }
public static bool operator !=(global::System.BitCheck8 obj1, byte obj2) { return (obj1 == null || obj1.Control != obj2); }
bool global::System.Collections.Generic.IDictionary<int, bool>.TryGetValue(int Key, out bool Value)
{
Value = false;
if (Key > -1 && Key < 8)
{
Value = this.IsBitSet(Key);
return true;
} else { return false; }
}
public static global::System.BitCheck8 operator +(global::System.BitCheck8 obj1, byte obj2)
{
if (obj1 == null) { return new global::System.BitCheck8(obj2); }
else
{
global::System.BitCheck8 a = new global::System.BitCheck8(obj1.Control);
for (int pos = 0; pos < 8; pos++) { if (global::System.BitCheck8.IsBitSet(obj2, pos)) { a[pos] = true; } }
return a;
}
}
public static global::System.BitCheck8 operator -(global::System.BitCheck8 obj1, byte obj2)
{
if (obj1 == null) { return new global::System.BitCheck8(obj2); }
else
{
global::System.BitCheck8 a = new global::System.BitCheck8(obj1.Control);
for (int pos = 0; pos < 8; pos++) { if (!global::System.BitCheck8.IsBitSet(obj2, pos)) { a[pos] = false; } }
return a;
}
}
public static global::System.BitCheck8 operator +(global::System.BitCheck8 obj1, global::System.BitCheck8 obj2) { return (obj2 == null ? obj1 : (obj1 + obj2.Control)); }
public static global::System.BitCheck8 operator -(global::System.BitCheck8 obj1, global::System.BitCheck8 obj2) { return (obj2 == null ? obj1 : (obj1 - obj2.Control)); }
public BitCheck8(bool Check0, bool Check1 = false, bool Check2 = false, bool Check3 = false, bool Check4 = false, bool Check5 = false, bool Check6 = false, bool Check7 = false)
{
this.Control = 0x0;
this[0] = Check0;
this[1] = Check1;
this[2] = Check2;
this[3] = Check3;
this[4] = Check4;
this[5] = Check5;
this[6] = Check6;
this[7] = Check7;
}
public BitCheck8(byte check) { this.Control = check; }
public BitCheck8() { this.Clear(); }
}
}
答案 1 :(得分:0)
使用移位运算符将索引转换为无符号long:
ulong bitIndexValue = 1ul << index;
// bitIndexValue = 0b0001 if index equals 0
// bitIndexValue = 0b0010 if index equals 1
// bitIndexValue = 0b0100 if index equals 2
检查未签名的long是否已将相同的位设置为1:
( value & bitIndexValue) == bitIndexValue;
// ( 0b0101 & 0b0100 ) == 0b0100 if index equals 2
这是完整的方法:
static bool CheckBit(ulong value, byte index)
{
if (index < 0 || index > 63) throw new ArgumentOutOfRangeException("index");
ulong bitIndexValue = 1UL << index;
return (value & bitIndexValue) == bitIndexValue;
}
以及使用方法:
Assert.IsTrue(CheckBit(4ul, 2)); // 0b0100 does contain 0b0100
Assert.IsTrue(CheckBit(5ul, 2)); // 0b0101 does contain 0b0100
Assert.IsFalse(CheckBit(8ul, 2)); // 0b1000 does not contain 0b0100