문제

그래서, 비트필드.특히 큰 비트 필드입니다.비트필드에서 개별 값을 조작하는 방법을 이해하지만 다음과 같이 큰 세트에서 이 작업을 수행하는 방법은 무엇입니까?

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 측면에서 비트를 나타내지 만 후드 아래에서는 int []를 사용한다고 생각합니다.

다른 팁

이것이 최선의 방법인지는 잘 모르겠지만 이것이 효과가 있을 수 있습니다(교대 근무 시간을 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비트보다 큰 시프트를 처리할 수 있습니다.조금 덜 보기 흉하게 보이도록 리팩토링할 수 있지만 테스트에서는 작동하고 성능 측면에서도 그리 나쁘지 않은 것 같습니다(실제로 큰 비트 세트를 처리하기 위해 내장된 무언가가 있는 경우는 제외).

    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