Shift 연산에 대해 들어보셨나요?

프로그래머용 계산기를 열어보면 <<, >> 라고 표기된 부분이 shift 연산 입니다.
그리 자주 사용하지는 않지만 알쓸신잡 같은 연산도구 입니다.
이걸 사용하는 이유는 통신 데이터 parsing 때문인데요.

제가 과거에 많이 사용하였던 Q4X 라는 레이저 센서의 IO-Link 통신 맵 입니다.
4차 산업이니 뭐니 해서 IO-Link 에 대한 사용이 점점 많아지는 추세인데요.
데이터를 보시면 16개 bit 1개의 워드로 되어 있습니다.
이 중 0번 bit는 센서에 거리에 따라 감지가 on/off 되는 것을 bit로 나타내고요.
1번 bit는 센서에 2번째 설정 거리에 따라 감지가 on/off 되는 것을 bit로 나타냅니다.
2번 bit는 현재 감지가 일정하게 되는 중인지 혹은 되다 한되다 출렁거리는 불안정한 상태인지를 나타내고요.
3번 부터 15번 까지는 거리값을 표현해 줍니다.
15번에서 3번 까지 데이터를 2진수로 기재하면
0001101110011 이죠?

계산기로 표현하면 10진수 부분에 883, 88.3mm를 이와같이 표현한 것을 알 수 있습니다.
그런데 워드 단위 (16bit) 그대로 해석하면 어떻게 되나요? 0b0001101110011101 이런 데이터 상태에서 10진수로 전환하면 7069 라는 데이터로 표현됩니다. 참고로 0b 로 표현하면 binary(2진수) 0x 로 표현하면 hexa(16진수) 를 의미합니다.
7069 에서 88.3mm 를 다시 따로 뽑아내야 하는데 어려움이 있는데요. 이럴 때 사용되는게 바로 shift 연산 입니다.

shift 는 변화 라는 의미도 있지만 옮기다 라는 뜻도 있습니다. 즉 데이터를 옮기거나 이동시키는 연산 입니다.

shift 연산은 위와 같은 규칙으로 동작합니다.
눈치 빠른 분들은 짐작 하시겠지만 필요없는 bit를 제거하는 기능을 하게되죠.
'제가 쓰는 언어에는 shift 연산이 없는데요?' 하시는 분들을 위해 tip 을 드리자면 사실은
N x 2^(shift 연산 수), N / 2^(shift 연산 수) 입니다.
예를 들어 숫자 13을 shift 연산으로 오른쪽으로 3칸 옮기는 연산의 경우
0b1101 즉 2^3 x 1 + 2^2 x 1 + 2^1 x 0 + 2^0 x 1 에서
0b1 이 되는데요. 이는
(2^3 x 1 + 2^2 x 1 + 2^1 x 0 + 2^0 x 1) / 2^3 이 되면서
2^(3-3) x 1 + 2^(2-3) x 1 + 2^(1-3) x 0 + 2^(0-3) x 1 이 되고, 소수 이하는 버리게 되면서
2^0 x 1 즉 0b1 이 되게 됩니다.

따라서 우리가 얻은 데이터 0b0001101110011101, 7069 를 우측 쉬프트 연산 3으로 3개 비트를 제거하면 원하는 0b001101110011 즉 883 이라는 데이터로 나오게 되며, 7069를 2^3, 8로 나눠줬을 때 몫도 같은 결과가 나오게 됩니다.
bit 데이터에 대한 parsing 에 위 내용을 기억하시면 아주 유용하게 사용할 수 있습니다.
shift 연산 없이 사칙연산으로 해석이 가능한데 굳이 shift 연산을 만든 이유는 프로그램 코드 가독성 때문인 것 같습니다.
아무 이유없이 / 8 하는 것 보다 3칸 이동했다 라는 해석이 가독성이 더 좋기 때문이죠.
여기서 한가지 더, 하위 bit 만 추출하고 싶을때는 어떻게 해야 될까요?

예를들어 Stability State 데이터만 추출하고 싶은 경우 가장 편한 방법은 논리연산 AND를 취하는 것입니다.
0b0001 1011 1001 1101
0b0000 0000 0000 0100
위 둘을 AND 연산을 하게되면

위와 같이 나오게 되죠, 3번 bit에 위치한 데이터 여서 결과값에 / 2^(3-1) 해주면 0,1 로 나오게 됩니다.
혹시라도 논리 연산이 없을 경우...나머지 값을 구하는 mod 함수를 이용하면 원하는 값을 추출할 수 있습니다.
PLC에서 Ladder 프로그램 작성하시는 분들이 간혹 위와같은 데이터 추출 방법을 몰라서 어려워 하시는 분들이 있습니다. 특히 시퀀스 위주로 작성하시다 보니 데이터 가공에 대해 어려워 하시는데 위 내용 참고하시어 원하는 데이터 추출을 편하게 하시기 바랍니다.
위에 나온 프로그래머용 계산기 관련해서 달력과 관련된 재미있는 내용 하나 공유드립니다.
2, 8, 10, 16 진수는 프로그램 하시면서 많이 접하게 되는데요. 2는 binary 에 약자 BIN, 8은 octal 의 약자 OCT, 10은 decimal 의 약자 DEC 16진수는 hexadecimal 의 약자로 HEX 로 사용합니다. 프로그램 하시는 분들은 익숙하실 텐데요. 특히 OCT 관련된 단어들은 8을 뜻하는 것들이 많습니다. 다리가 8개인 문어도 octopus 라는 이름을 가지고 있고요, 달력에서도 October 가 있죠...
엥? October는 8월이 아니라 10월인데요??!!
이상하죠? ^^
10진수를 뜻하는 Decimal 도 달력에서는 12월이 됩니다. ㅎㅎ 왜그럴까요?
저도 정확한 기원은 잘 모르지만 로마에서 초기에 달력이 만들어 지면서 계산 오류가 있었고, 이 때문에 2개 달을 추가하게 됩니다. 여기서 갑자기 들어온 추가된 달이 July, August 입니다. 이는 당시 로마에서 유명했던 율리우스 카이사르 ( Julius Caesar ) 와 아우구스투스 (Augustus) 황제의 이름이 들어간 것입니다.
달력에 들어간 사람 이름에 대한 내용은 나중에 재미있는 알쓸신잡 처럼 알아두시면 좋겠습니다.
shift 연산에 대해 내용은 간단한데 너무 장황하게 늘어놓았네요. ( 재미있게 쉬어가도록 하려다가 머리만 더 복잡하게 해드린 것 같습니다. ) 대충 저런게 있다 정도로 넘기시다가 나중에 필요하실 때 다시 찾아보시면 좋을 것 같습니다.
'Codesys 3.5' 카테고리의 다른 글
| 부록 #1 ASCII CODE (0) | 2025.10.15 |
|---|---|
| Codesys #6 반복문, 조건문 (0) | 2025.10.15 |
| Codesys #5 변수 Variable (전역변수, 지역변수, Retain 변수) (0) | 2025.10.14 |
| Codesys #4-1 POU (Program, Function Block Diagram, Function) (0) | 2025.07.22 |
| Codesys #3-2 AND 함수와 데이터 수동 입력 (0) | 2025.07.21 |






































































