다중 Checkbox 선택 값을 선택된 합산 값으로 DB 에서 저장하고,
이를 읽어서 선택된 Checkbox 를 설정해야 한다는 문의가 들어 왔다.
문의에 답변을 해준 김에 정리를 해 놓도록 한다.
Unix를 써본 사람이라면 다중 플래그에 대한 것을 잘 알고 있을 것이다.
Unix에서 권한코드 (Read, Write, Execute, …) 가 같은 맥락이기 때문이다.
비트 연산
비트 연산에서 Shift 연산자를 제외하면 & (and), | (or), ^ (xor), ~ (비트 반전)의
4개 연산자가 존재한다.
- & 연산은 양쪽 모두 1인 경우만 1을 반환한다.
- | 연산은 양쪽 모두 0인 경우만 0을 반환한다.
- ^ 연산은 | 과 반대로 모두 1인 경우만 0을 반환한다.
- ~ 연산은 모든 비트의 값을 반전시킨다. 즉 1의 보수(반대값)를 나타낸다.
물론 대상은 unsigned 정수를 기준으로 한다. 따라서 선언은 16비트 선언을 기준으로 한다.
샘플 코드
백문이 불여일타이니 코드부터 알아보도록 한다.
public static final int A = 0x01; // 0000 0001
public static final int B = 0x02; // 0000 0010
public static final int C = 0x04; // 0000 0100
public static final int D = 0x08; // 0000 1000
public static final int E = 0x10; // 0001 0000
public static final int F = 0x20; // 0010 0000
public static final int G = 0x40; // 0100 0000
public static final int H = 0x80; // 1000 0000
위의 선언과 이진 값에서 보이는 것과 같이 1, 2, 4, 8, ... 처럼
이진수로 증가하는 값이어야 하고 각 비트의 중복이 없어야 하는 것이 기본이다.
만일 사용자가 A 와 D를 선택했다고 하면 아래와 같이 처리가 된다.
0000 0001 // A
0000 1000 // D
---------
0000 1001 // A | D
즉 | 연산이 되어 0000 1001 인 값이 나오는 것이다.
만일 여기서 D를 끄고 싶은 경우는 어떻게 해야 할까?
답은 간단하다. 위에서 보수(반대값)에 대해서 알아 보았기 때문에
결과에 D 의 보수 값인 1111 0111 을 & 연산해 주면 된다.
0000 1001 // A | D
1111 0111 // ~ D
---------
0000 0001 // (A | D) & (~D)
따라서 하나의 변수에 여러 개의 플래그 값을 관리할 수 있게 된다.
int flag = 0x00; // 변수 초기화
flag |= A; // A 선택
flag |= D; // D 선택
flag &= ~D; // D 선택 해제
이런 원리를 이용해서 특정한 값에 대해서 플래그가 선택되었는지 여부를 확인할 수 있다.
if ((flag & A) == A); // A 선택 상태
if ((flag & !(A | B)) != 0x00); // A, B 이외에도 다른 플래그가 선택되어 있는 상태
위와 같이 하나의 값을 여러 개의 플래그로 사용하는 경우에 비트 연산이 사용되는 것이다.
댓글
댓글 쓰기