2013-04-27 2 views
1

나는 비트 연산자와 장난하고있어, 나는 부호없는 8 비트 값에 부정적인 바이트로 변환하려고했다,이 사람들이 무엇을 제안이다 :왜 자바에서 바이트 단위의 비트 AND는 이렇게합니까?

System.out.println(-20 & 0xFF); //bitwise AND on negative number and 255 

그래서,이 완벽하게 작동하고, 236을 반환 ,하지만 왜? 내가 아는 한 :

00010100 //binary representation of -20 
11111111 //binary representation of 0xFF or 255 
-------- 
00010100 //it returns the same exact thing, so it's either -20 or 20 

왜 작동합니까? 나는 아주 간단한 것을 놓친 것 같지만 그것을 이해할 수는 없다.

또한 256보다 작은 양수로 입력하면 동일한 숫자가 반환됩니다. 나는 자바가이 숫자들을 가지고 무엇을하는지 이해하지 못하는 것 같다.

+1

-20! = 20이므로 표현도 동일하지 않습니다. –

답변

4

자바의 리터럴을 - 2 초에서

음수를 만들기 위해 보완, 모든 비트가 뒤집 (1 초 보완)과 1 (이 작업을 2 초 보완하고) 추가 int의 형식입니다.

11111111 11111111 11111111 11101100 //-20 -ve nos are stored in 2's compliment form 
& 00000000 00000000 00000000 11111111 // 0xFF 
    -------- -------- -------- -------- 
    00000000 00000000 00000000 11101100 // 236 

당신이 20 & 0xFF을 perfrom 때 negetaive 값이 2의 칭찬의 형태로 저장되기 때문에, 당신은 값 (236)

를 얻을 이런 일이 발생 :

당신이 -20 & 0xFF을 말할 때,이 일어나는 것이다
00000000 00000000 00000000 00010100 // 20 -ve nos are stored in 2's compliment form 
& 00000000 00000000 00000000 11111111 // 0xFF 
    -------- -------- -------- -------- 
    00000000 00000000 00000000 00010100 // 20 
+0

아, 이제 알겠습니다. 아마 나를 혼란스럽게하는 2의 칭찬 양식 일 겁니다. 이것을 바로 알겠습니다 : -128에서 -1 (포함) 사이의 음수를 저장하면 256을 7 비트 표현으로 저장하고 8 번째 비트는 음수인지 아니면 음수인지를 나타내는 데 사용됩니다 긍정적입니다, 맞습니까? 이제는 나를 혼란스럽게 만들었던 유일한 방법은 첫 번째 예에서는 -20의 시작 부분에 24 1이 추가된다는 것입니다. 왜 1, 왜 0이 아닌가? 그게 지금 당장 나를 괴롭 히고있는 유일한 것입니다. – ZimZim

+0

@ user1007059 :'byte' 변수를 가지고 있다면, 8 번째 비트가 부호 저장에 사용됩니다. 그러나 위의 경우에서와 같이 리터럴을 사용하면 리터럴은 크기가 아무리 작아도 int로 저장됩니다. 따라서 '-20 & 0xFF'를 쓸 때, 각각 32 비트의 두 개의 int가 생성되고, MSB, 즉 32 번째 비트가 부호 저장에 사용됩니다. 첫 번째 예제에서 숫자는 2의 칭찬과 2의 칭찬 양식에 있기 때문에 앞의 1이 표시됩니다. 첫 번째 1 앞에 모든 비트가 뒤집 힙니다. 즉 0은 1이되고 1은 1이됩니다. –

+0

감사합니다. 이제 이해합니다. 대부분이. 나는 바보처럼 느끼지 않고 계속 비트와 바이트를 뒤범벅 할 수있다 : D – ZimZim

1

바이트는 8 비트로 유지 된 서명 값이고 가장 왼쪽 비트는 부호 비트로서 사용된다 -128

127의 범위 일 수있다.

System.out.println(-20 & 0xFF);은 바이트와 관련이 없습니다. 이것은 int 연산입니다.

-20의 이진 표현, 바이트는 그대로 : 1110_1100

1110_1100 & 1111_1111 = 1110_1100

당신이 서명하려는 경우가 놀 문자, 그러나 당신이 행복하지 않을거야 . 현실적으로 Java는 서명이 없습니다.

부정적 측면에 저장되어있는 형태의 '보수 2 초', 예를 들면 :

1111_1111 == -1

왜?

그래서

0000_0000 - Zero 
-0000_0001 - minus one 
--------- 
1111_1110 - Ones complement - (this would be xor 1111_1111) 
+0000_0001 - plus one - we're converting to 2s complement, not doing math 
--------- 
1111_1111 - -1 in 2s complement 
+0

바이트의 내부에 -20을 저장하려고 시도한 다음 & 0xFF를 사용했기 때문에 "바이트"라고 말하면 작동했습니다. 또한 11101100은 -108이 아닙니까? 가장 왼쪽의 비트는 마이너스를 나타내며 나머지는 108이 될 실제 수를 나타냅니다. 여기서 내가 무엇을 놓치고 있습니까? – ZimZim

+0

"2s complement"라고 불리우며 내 게시물을 편집합니다. –

+0

부호없는 누락이 실제로 두 가지 위치에만 있습니다. 관계 연산자와 확장 변환입니다.char로 전환하는 것은 거의 어리석은 일입니다. 거의 모든 연산을 수행하면 gorry가 서명 한 모든 문제가 int로 반환되기 때문입니다 (중간 결과에는 숨겨져 있음). 2가 보수의 세부 사항을 알면 변수가 서명 된 것으로 취급되는 경우에도 서명되지 않은 데이터로 올바르게 작업 할 수 있습니다. Java 나 다른 언어가 아닌 지식을 적절하게 대체 할 수는 없습니다. – Durandal