C# 의 Shift 비트 연산 정리
Programming/C# / 2013. 12. 18. 12:24
우선, 모델이 되는 숫자 하나를 골라볼까요? ^^
uint un = 2320987651; int n = 2020987651; OutputBitText(un + "[unsigned] ==> \t", un); OutputBitText(n + "[signed] ==> \t", n); private static void OutputBitText(string text, uint n) { Console.WriteLine(text + " " + Convert.ToString(n, 2).PadLeft(32, '0')); } private static void OutputBitText(string text, int n) { Console.WriteLine(text + " " + Convert.ToString(n, 2).PadLeft(32, '0')); } // 출력 결과 2320987651[unsigned] ==> 10001010010101110111011000000011, 2320987651 -1753885949[signed] ==> 10010111011101011101001100000011, -1753885949
여기서 기본적인 C# 의 Bit Shift 연산자 (<<, >>) 를 사용해 보겠습니다.
2320987651[unsigned] ==> 10001010010101110111011000000011, 2320987651 [unsigned] >> 4 ==> 00001000101001010111011101100000, 145061728 [unsigned] << 4 ==> 10100101011101110110000000110000, 2776064048 -1753885949[signed] ==> 10010111011101011101001100000011, -1753885949 [signed] >> 4 ==> 11111001011101110101110100110000, -109617872 [signed] << 4 ==> 01110111010111010011000000110000, 2002595888
보시는 것처럼, C# 의 기본 Bit Shift 연산자는 다음과 같은 규칙이 있습니다.
unsigned 의 경우, 밀려난 비트 들에 대한 처리를 하지 않고 최상위 비트에 대한 처리도 없음 signed 의 경우, 우측 shift 연산자는 최상위 부호 비트를 유지하면서 밀려난 비트들에 대한 처리를 하지 않고, 좌측 shift 연산자는 부호 비트를 지키지 않고, 역시 밀려난 비트들에 대한 처리를 하지 않는다.
자, 그럼 여기서 부호 비트는 상관없이 순수하게 rotation 식의 shift 연산을 수행하려면 어떻게 해야 할까요? 이를 위해서는 다음과 같은 보조 함수를 만들어줘야 합니다.
C# bitwise rotate left and rotate right ; http://stackoverflow.com/questions/812022/c-sharp-bitwise-rotate-left-and-rotate-right
static uint UnsignedLeftShift(uint number, int shift) { return (uint)((number << shift) | (number >> (32 - shift))); } static uint UnsignedRightShift(uint number, int shift) { return (uint)((number >> shift) | (number << (32 - shift))); }
사용법은 unsigned 의 경우 그냥 사용하면 되지만, signed 의 경우에는 unsigned 형변환을 해줘야만 정상적으로 rotation 이 됩니다.
OutputBitText("[rotation] >> 4 ==> \t\t", UnsignedRightShift(un, 4)); OutputBitText("[rotation] << 4 ==> \t\t", UnsignedLeftShift(un, 4)); OutputBitText("[rotation] >> 4 ==> \t\t", UnsignedRightShift((uint)n, 4)); OutputBitText("[rotation] << 4 ==> \t\t", UnsignedLeftShift((uint)n, 4)); // 출력 결과 2320987651[unsigned] ==> 10001010010101110111011000000011, 2320987651 [rotation] >> 4 ==> 00111000101001010111011101100000, 950368096 [rotation] << 4 ==> 10100101011101110110000000111000, 2776064056 -1753885949[signed] ==> 10010111011101011101001100000011, -1753885949 [rotation] >> 4 ==> 00111001011101110101110100110000, 964123952 [rotation] << 4 ==> 01110111010111010011000000111001, 2002595897
마지막으로 자바의 unsigned right shift 연산자(>>>) 에 해당하는 C# 의 코드는 어떻게 구현해야 할까요?
비교를 위해 우선 자바의 비트 처리 값을 확인해 보면 다음과 같은 데요.
==== Java ==== n == 320987651 == 00010011001000011110001000000011 -n == -320987651 == 11101100110111100001110111111101 n >>> 3 == 40123456 == 00000010011001000011110001000000 -n >>> 3 == 496747455 == 00011101100110111100001110111111
즉, 최상위 비트를 무시하고 무조건 shift 연산만을 수행하는 것입니다. 이에 대한 C# 의 동일한 작업은 다음의 글에서 소개하는 것처럼 간단합니다.
bitwise unsigned right shift >>> ; http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/6c892d10-75ff-4f4e-a555-3017f72ec170/
static int TripleRightShift(int number, int shift) { return (int)((uint)number >> shift); } // 출력 결과 320987651 >>> 3 == 00000010011001000011110001000000, 40123456 -320987651 >>> 3 == 00011101100110111100001110111111, 496747455
보시는 것처럼, 자바의 >>> 연산자와 동일한 출력 결과를 보입니다.
그럼... 정리가 다 된 것 같군요. ^^
(첨부된 파일은 위의 코드를 포함한 예제 프로젝트입니다.)
부가적으로 다음의 글도 예전에 쓴 적이 있답니다. ^^
C# - Right operand 가 음수인 Shift 연산 결과 ; http://www.sysnet.pe.kr/2/0/1008
반응형
'Programming > C#' 카테고리의 다른 글
제네릭(Generic)과 제약조건 (0) | 2014.03.13 |
---|---|
Reading Excel Files in C# (0) | 2014.03.12 |
Copy List to List (0) | 2013.10.10 |
Sorting (0) | 2013.10.02 |
C# 에서 콘솔 프로그램을 숨기는 방법 ( Using ProcessStartInfo Class ) (0) | 2013.07.23 |