레이블이 보수인 게시물을 표시합니다. 모든 게시물 표시
레이블이 보수인 게시물을 표시합니다. 모든 게시물 표시

golang xor bitwise 사용하기

// golang 에는 not 비트연산자(C 에서는 ~)가 없어 XOR 를 이용해 구한다.
// XOR 를 단항연산으로 사용시 보수(not)를 구할 수 있다.
// https://go.dev/ref/spec#Arithmetic_operators
// +x                          is 0 + x
// -x    negation              is 0 - x
// ^x    bitwise complement    is m ^ x  with m = "all bits set to 1" for unsigned x
//                                       and  m = -1 for signed x
// 위 설명대로 ^x 는
// x 가 unsigned 라면 0xfffff..(모든비트1) ^ x 로 동작하고
// x 가 signed 라면 -1 ^ x 로 동작한다

// not 구하기
var aa uint = 5 // 0101
fmt.Printf("%3d(%10b)\n", aa, aa)
// 모든 비트가 1로 설정된 m 과 xor 되어 not(비트 반전, 1의보수)결과를 구할 수 있다.
fmt.Printf("%3d(%10b)\n", ^aa, ^aa)
// 0xf 등으로 xor 해서 비트 범위를 줄여서 not 결과를 만들 수도 있다.
fmt.Printf("%3d(%10b)\n", 0xf^aa, 0xf^aa)

bb := 5 // 0101
// singed 형이라면 위 설명대로 -1 ^ bb 가 된다.
fmt.Printf("%3d(%10b)\n", ^bb, ^bb)

// 양수 -> 음수, MSB(Most Significant Bit) 는 음수가 된다.
// bb 는 signed 라서 위 설명처럼 ^bb 하면 -1 과 xor 된다.
// 여기에 +1(2의보수)를 하면 음수가 된다.
fmt.Printf("%3d(%8b) -> %3d(%8b) -> %3d(%8b)\n", bb, bb, ^bb, ^bb, ^bb+1, ^bb+1)

bb = -5
// 음수 -> 양수, MSB(Most Significant Bit) 는 양수가 된다.
// bb 는 signed 라서 위 설명처럼 ^bb 하면 -1 과 xor 된다.
// 여기에 +1(2의보수)를 하면 양수가 된다.
fmt.Printf("%3d(%8b) -> %3d(%8b) -> %3d(%8b)\n", bb, bb, ^bb, ^bb, ^bb+1, ^bb+1)

# 참고

보수(complement)로 계산

# 보수(complement, 보충해주는 수)를 사용해서 계산하기
# 1의 보수(one's complement), 모든 비트 반전
ex) 10(1010) - 3(0011) = 7(0111)
 1010(10)   
+1100(3에 대한 1의 보수,12)
-----
10110 
맨앞 캐리 발생한 경우 캐리는 버리고 +1
 0110
+   1
-----
 0111 => 7

ex) 3(0011) - 10(1010) = -7(1111)
-10 의 음수 MSB(Most Significant Bit)은 제외하고 계산
 0011
+0101(10에 대한 1의 보수)
-----
 1000
맨앞 캐리가 발생하지 않으면, 1의 보수로 변경하고 -음수 설정
 0111 => MSB 음수(1)로, => 1111


# 2의 보수(two's complement), 1의 보수 +1
ex) 10(1010) - 3(0011) = 7(0111)
 1010(10)   
+1101(3에 대한 2의 보수,12)
-----
10111
맨앞의 캐리는 버린다. => (0111)

ex) 3(0011) - 10(1010) = -7(1111)
-10 의 음수 MSB(Most Significant Bit)은 제외하고 계산
 0011
+0110(10에 대한 2의 보수)
-----
 1001
맨앞 캐리가 발생하지 않으면, 2의 보수로 변경하고 -음
 0110
+   1
-----
 0111, => MSB 음수(1)로, => 1111


# 2의 보수를 사용하는 이유
양수는 보수를 취하지 않는다. +0(0000) => 0000 이다.
음수의 경우 보수를 취해야 하는데,
1의 보수의 경우
-0이 1111로 표현, -0(1111), 맨앞 부호 비트를 버리면 (111) 도 -0이 된다.

2의 보수의 경우
-0(1000) => (1111) + (1) = (10000), 맨앞 부호 비트 버리면 (000)이 -0이 된다.

2보의수는 -0,+0을 하나로 표현돼 저장공간을 1의보수에 비해 1개더 사용할 수 있다.