簡體   English   中英

如何設置/獲取UInt64的位?

[英]How to set/get bits of a UInt64?

我正在使用UInt64來存儲位。 一個示例是UInt64 val = 0b0001_0000 現在,我希望能夠確定是否在特定位置設置了位。 例如,我想知道val是否設置了第4位(使用從零開始的索引)。 如果要對此進行硬編碼,則可以使用AND和OR運算符對一個臨時變量進行操作,清除除第4個位以外的所有位並檢查該值。 但是,我想實現一種更動態的方法來執行此操作,因此不需要使用一堆不同的位文字(例如0b0001_0000進行檢查。

我嘗試解析動態創建的類似"0b0001_0000"的字符串,但我對UInt64Byte等沒有好運。

您可以使用Left(<<)或Right(>>)運算符將所有int,long,uint,ulong等位導航到更大的數值。

請參閱MSDN文檔上的這篇文章: 左移運算符右移運算符

像這樣(我從“左移運算符”頁面獲取了示例):

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
*/

更新

更好的是,從此站點中的C中的位處理中查看此完整的實現(基於BYTE結構-只需將其更改為LONG或ULONG):

更新2

我最終在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(); }
    }
}

使用位移運算符將索引轉換為無符號長型:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM