IT/자바

이진논리연산자

Beautifulkim 2018. 4. 19. 15:29

class 이진논리연산자 

{

public static void main(String[] args) 

{

int a = 7;

int b = 5;


System.out.printf("%32s\n", Integer.toBinaryString(a));

System.out.printf("%32s\n", Integer.toBinaryString(b));


System.out.printf("%32s\n", Integer.toBinaryString(a&b));

System.out.printf("%32s\n", Integer.toBinaryString(a|b));

System.out.printf("%32s\n", Integer.toBinaryString(a^b));


// 년, 월, 일 분리 프로그램

int birthday = 0x19880815;


//    0x19880815

//    0x    1988(0815) 괄호는 소멸

//    0x00001988(0815)

int year = birthday >>> 16;

//    0x19880815

//    0x00198808(15) 괄호는 소멸 0000 1000->08   

// &    0x000000ff 1111 1111->ff

        //16진수  : 0~9, a(10), b(11), c(12), d(13), e(14), f(15)

int month = birthday >> 8 & 0x000000ff;

int day   = birthday & 0xff; // 0xff 와 0x000000ff 서로 같음


System.out.printf("출생년도 : %x년\n", year);

System.out.printf("출생월 : %02x월\n", month);

System.out.printf("출생일 : %02x일\n", day);


/*

shift : 이동하다.

2진수는 2칸

8진수는 3칸

16진수는 4칸


year = birthday >>> 16;

year를 구하기위해

year = 0x19880815 >>> 16; 

위의 코드에서 >>> 오른쪽으로 이동하는데 16진수(4칸)을 짤라낸다는 의미

0x00001988(0815)

*/



// birthday = 0x19880815;

//   0xffff00ff;

// 방법1) &이용한 소거

birthday = birthday & 0xffff00ff;

System.out.printf("%x\n", birthday);


//방법2) ^ 이용한 소거

// birthday = birthday ^ 0x19880815; 1000 0001 1001

//                       0x00000800; 1000 0000 0000

birthday = birthday ^ 0x00000800;

System.out.printf("%x\n", birthday);


// 월자리에 12 추가

// birthday = 0x19880015;

// |   0x00001200;

birthday = birthday | 0x00001200;

System.out.printf("%x\n", birthday);


}

}

//~ 는 반대로 바꿈

/*

1. 시프트 연산자


1)  >> : 오른쪽으로  주어진 비트 수만큼 이동 

       : 앞에 비어 있는 빈칸은 부호 비트로 채운다

2)  << : 왼쪽으로 주어진 비트 수만큼 이동 

       : 뒤에 비어 있는 빈칸은 0으로 채운다.






*


문제 : 178

128  64  32  16  8  4  2  1 -> 승수

1    0    1   1  0  0  1  0 -> 2진수로 변환한 코드

바로 위에서 1이 표시된 부분의 

승수를 모두 더하면 

178이라는 값이 나옴


<시프트 연산자>

비트 열을 좌우로 지시한 만큼 이동시키는(shift) 연산자를 말한다.

C언어 : >> 과 << 만 있음

자바언어 : >>> 연산자도 있음


○ 왼쪽 시프트 연산자 <<

128  64  32  16  8  4  2  1 -> 승수

1    0    1   1  0  0  1  0 -> 2진수로 변환한 코드

178 << 2 : 178 의 이진코드를 왼쪽으로 2비트 시프트 한다.

  10110010 : 2 진수로 변환한 코드 값

  1011001000 : 

왼쪽으로 두칸 밀면서, 비게 되는 오른쪽 두칸은 0 으로 채운다.

그런데, 문제는 왼쪽으로 밀면서 기존의 크기를 넘어서기 때문에 

왼쪽으로 넘어선 2개의 비트는 삭제(11001000)

따라서, 10110010 을 왼쪽으로 밀면 

왼쪽 두개 비트인 10 은 삭제되고, 

오른쪽의 2개 비트는 0으로 채워져

결과값은 11001000 이 된다.


문제 : 178

128  64  32  16  8  4  2  1 -> 승수

1    0    1   1  0  0  1  0 -> 2진수로 변환한 코드

○ 오른쪽 시프트 연산자 >>

178 >> 2 : 178의 이진코드를 오른쪽으로 2 비트 시프트 한다.

  10110010

1110110010

오른쪽으로 2비트 이동한후, 비게되는 왼쪽의 2개비트는 1로 채워지고, 오른쪽에서 2비트 넘어간 부분은 삭제된다.

따라서, 10110010 을 오른쪽으로 2비트 시프트하면, 11101100 이 된다.

그런데, 주의할점은, 오른쪽으로 밀면서 왼쪽에 비게되는 비트부분이 무조건 1 로 채워지는 것이 아니라,

밀기전의 최초 첫째자리 값과 동일한 값으로 채워진다는 것이다.

여기에서는 밀기전의 첫째자리값이 1 이었으므로, 1 로 채워진 것이다.


문제 : 178

128  64  32  16  8  4  2  1 -> 승수

1    0    1   1  0  0  1  0 -> 2진수로 변환한 코드

○ 논리 오른쪽 시프트 연산자 >>>

178 >>> 2 : 오른쪽으로 2 비트 시프트한다.

자바에 추가된 논리 시프트는 오른쪽으로 밀면서 비게되는 앞쪽 비트를 무조건 0 으로 채워넣는 것이다.

  10110010 -> 밀기전 2진코드

  00101100 -> 밀고나서 2진코드

으로 되는 것으로,

역시 오른쪽으로 밀려난 2개 비트 10 은 삭제되고, 

비게되는 왼쪽 2비트는 무조건 0으로 채워진다.

따라서 10110010 을 오른쪽으로 논리 시프트 하면, 00101100 이 된다.


예시)

--------------------------------------

public class a{

  public static void main(String [] args){

    byte a = 10;  // 00001010

    byte b = 9;   // 00001001

    byte c = 1;  //시프트할 칸수

    System.out.println(a + " & " + b + " = " + (a&b));  //논리합

    System.out.println(a + " | " + b + " = " + (a|b));  //논리곱

    System.out.println(a + " ^ " + b + " = " + (a^b));  //배타적 논리합(xor)

    System.out.println("~10 = " + (~a));  //a 의 보수(반전)

    System.out.println(a + " << " + c + " = " + (a<<c));  //왼쪽 1비트 시프트(뒤를 0 으로 채움)

    System.out.println(a + " >> " + c + " = " + (a>>c));  //오른쪽 1비트 시프트(앞을 밀리기전 첫째자리와 동일한 비트로 채움)

    System.out.println(a + " >>> " + c + " = " + (a>>>c)); //오른쪽 1비트 논리 시프트(앞을 0 으로 채움)

    System.out.println(-1 * a + " >> " + c + " = " + (-1*a >> c));

  }

}

--------------------------------------

/*

출력:

10 & 9 = 8    : 00001000

10 | 9 = 11   : 00001011

10 ^ 9 = 3    : 00000011

~10 = -11     : 11110101

10 << 1 = 20  : 00010100

10 >> 1 = 5   : 00000101

10 >>> 1 = 5  : 00000101

-10 >> 1 = -5 : 11111011

*/

부호가 붙은 정수형에서는 최상위 비트를 부호비트로 사용한다.

0 은 + 를 표시하고, 나머지 비트로 수를 표시한다.

1은 - 를 표시 하고, 나머지 비트를 반전하여 1 을 더한값이 절대값이 된다.


----------------------------------------

쉬프트연산자 >>, >>> 차이점이요.


양의 숫자를 쉬프트 시킬때는 차의가 없습니다.


하지만 음의 숫자는 2진수로 표시할때 맨앞에 부호비트 1이 붙습니다.


>>연산자의 경우는 부호비트는 고정되고 쉬프트 되지만

>>>연산자는 부호비트도 함께 쉬프트가 됩니다.


ex) 


System.out.println(-300>>>2);

System.out.println(-300>>2);


실행시키면 


1073741749 

-75


가 됩니다.

*/






------------------

수업시간 메모


오른쪽으로 밀릴때 

양수면 0으로 채우고

음수면 부호로 채움


왼쪽으로 밀면 값이 커짐

32 16 8 4 2 1의 논리에 의해


오른쪾으로 밀면 감소 되고

왼쪽으로 밀면 증가함


-1을 오르쪽으로 밀면 부호비트 1로 채워짐

(빈공간은 부호로 채움)


양수로 밀땐 두개짜로리로 밀든 결과는 ㄱ같음


음수로 2개를 밀면 빈공간은 부호(1)로 채움

움수로 3개 짜리로 밀면 빈공간은 0으로 채움


2개짜리로 오른쪽으로 밀때 부호로채우고

3개짜리는 0으로 채움