سؤال

وهكذا، bitfields. bitfields على وجه التحديد، واسع. وأنا أفهم كيفية التعامل مع القيم الفردية في bitfield، ولكن كيف أذهب عن القيام بذلك على مجموعة كبيرة، مثل يقول:

uint[] bitfield = new uint[4] { 0x0080000, 0x00FA3020, 0x00C8000, 0x0FF00D0 };

والمشكلة محددة أواجه يقوم به اليسار واليمين التحولات التي تحمل من خلال عبر مجموعة كاملة. هكذا على سبيل المثال، إذا فعلت >> 4 على مجموعة المذكورة أعلاه، كنت في نهاية المطاف مع:

uint[4] { 0x0008000, 0x000FA302, 0x000C800, 0x00FF00D };

والآن، وهو (أكثر من اللازم) خوارزمية التبسيط هنا قد تبدو شيء من هذا القبيل (وهذا هو لي ريتينغ متاحة على الطاير):

int shift = 4;
for (int i = 0; i <= shift; i++) {
    for (int j = bitfield.GetUpperBound(0); j > 0; j--) {
        bitfield[j] = bitfield[j] >> 1;
        bitfield[j] = bitfield[j] + ((bitfield[j-1] & 1) << (sizeof(uint)*8));
    }
    bitfield[0] = bitfield[0] >> 1;
}

هل هناك أي شيء بنيت في ذلك قد يخفف العمل مع هذا النوع من البيانات؟

هل كانت مفيدة؟

المحلول

ما الذي يجعلك تعتقد أن يستخدم BitArray bools داخليا؟ ويستخدم القيم المنطقية لتمثيل البتات من حيث API، ولكن تحت غطاء محرك السيارة وأعتقد أنه يستخدم كثافة العمليات [].

نصائح أخرى

ولست متأكدا إذا كان هو أفضل طريقة للقيام بذلك، ولكن هذا يمكن أن تعمل (تقييد التحولات لتكون في حدود 0-31.

    public static void ShiftLeft(uint[] bitfield, int shift) {

        if(shift < 0 || shift > 31) {
            // handle error here
            return;
        }

        int len = bitfield.Length;
        int i = len - 1;
        uint prev = 0;

        while(i >= 0) {
            uint tmp        = bitfield[i];
            bitfield[i] = bitfield[i] << shift;
            if(i < len - 1) {
                bitfield[i] |= (uint)(prev & (1 >> shift) - 1 ) >> (32 - shift);
            }
            prev = tmp;

            i--;
        }

    }

    public static void ShiftRight(uint[] bitfield, int shift) {

        if(shift < 0 || shift > 31) {
            // handle error here
            return;
        }
        int len = bitfield.Length;
        int i = 0;
        uint prev = 0;

        while(i < len) {
            uint tmp        = bitfield[i];
            bitfield[i] = bitfield[i] >> shift;
            if(i > 0) {
                bitfield[i] |= (uint)(prev & (1 << shift) - 1 ) << (32 - shift);
            }
            prev = tmp;

            i++;
        }

    }

وPD: مع هذا التغيير، يجب أن تكون قادرة على التعامل مع التحولات أكبر من 31 بت. يمكن ريفاكتوريد لجعلها تبدو أقل قليلا القبيح، ولكن في بلدي التجارب، وأنها تعمل وأنها لا يبدو الأداء الحكمة سيئة للغاية (ما لم يكن هناك في الواقع شيء بنيت في التعامل مع bitsets كبير، والتي يمكن أن يكون هذا هو الحال).

    public static void ShiftLeft(uint[] bitfield, int shift) {

        if(shift < 0) {
            // error
            return;
        } 

        int intsShift = shift >> 5;

        if(intsShift > 0) {
            if(intsShift > bitfield.Length) {
                // error
                return;
            }

            for(int j=0;j < bitfield.Length;j++) {
                if(j > intsShift + 1) {     
                    bitfield[j] = 0;
                } else {
                    bitfield[j] = bitfield[j+intsShift];
                }
            }

            BitSetUtils.ShiftLeft(bitfield,shift - intsShift * 32);
            return;
        }

        int len = bitfield.Length;
        int i = len - 1;
        uint prev = 0;

        while(i >= 0) {
            uint tmp    = bitfield[i];
            bitfield[i] = bitfield[i] << shift;
            if(i < len - 1) {
                bitfield[i] |= (uint)(prev & (1 >> shift) - 1 ) >> (32 - shift);
            }
            prev = tmp;

            i--;
        }

    }

    public static void ShiftRight(uint[] bitfield, int shift) {

        if(shift < 0) {
            // error
            return;
        } 

        int intsShift = shift >> 5;

        if(intsShift > 0) {
            if(intsShift > bitfield.Length) {
                // error
                return;
            }

            for(int j=bitfield.Length-1;j >= 0;j--) {
                if(j >= intsShift) {        
                    bitfield[j] = bitfield[j-intsShift];
                } else {
                    bitfield[j] = 0;
                }
            }

            BitSetUtils.ShiftRight(bitfield,shift - intsShift * 32);
            return;
        }


        int len = bitfield.Length;
        int i = 0;
        uint prev = 0;

        while(i < len) {
            uint tmp    = bitfield[i];
            bitfield[i] = bitfield[i] >> shift;
            if(i > 0) {
                bitfield[i] |= (uint)(prev & (1 << shift) - 1 ) << (32 - shift);
            }
            prev = tmp;

            i++;
        }

    }
<ع> استخدام طرق الإرشاد، هل يمكن أن تفعل هذا:

public static class BitArrayExtensions
{
    public static void DownShift(this BitArray bitArray, int places)
    {
        for (var i = 0; i < bitArray.Length; i++)
        {
            bitArray[i] = i + places < bitArray.Length && bitArray[i + places];
        }
    }

    public static void UpShift(this BitArray bitArray, int places)
    {
        for (var i = bitArray.Length - 1; i >= 0; i--)
        {
            bitArray[i] = i - places >= 0 && bitArray[i - places];
        }
    }
}

ولسوء الحظ، لم أتمكن من التوصل إلى طريقة لتزيد من مشغلي التحول. (ويرجع ذلك أساسا وختم BitArray).

إذا كنت تنوي التلاعب ints أو uints، يمكنك إنشاء طرق الإرشاد لإدخال بت إلى / استخراج بت من BitArray. (BitArray لديها منشئ التي تأخذ مجموعة من ints، ولكن هذا يستغرق سوى لك هذا الحد).

وهذا لا يشمل التحول على وجه التحديد، ولكن يمكن أن تكون مفيدة للعمل مع مجموعات كبيرة. انها في C، ولكن أعتقد أنه يمكن أن تتكيف بسهولة مع C #

هل هناك حد عملي لحجم أقنعة بت؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top