Java에서 바이트 범위가 -128 ~ 127 인 이유는 무엇입니까?


79

나는 바이트가 취할 수있는 가장 낮은 값이 왜 -128. 이진수 127이기 때문에 가장 높은 값이라는 것을 알 수 있습니다 01111111. 그러나 하나는 -1288 비트로 만 표현 되고 그중 하나는 부호에 사용됩니까? 양수 128은 이미 8 비트입니다. 즉 10000000, 음수 부호를 나타내려면 9 번째 비트가 필요합니다.

누군가 제게 이것을 설명해 주시겠습니까?



1
그것은 다른 정수 유형의 유사 short, int하고 long.
starblue

11
더 좋은 질문은 why java byte type is not a range of 0..255? 사실 많은 사람들이이 질문을합니다. 대부분의 언어에서 byte유형이 서명되지 않았습니다.하지만 자바 byte에서도 서명이되어 있습니다. 저 (그리고 다른 많은 사람들)는 그것이 첫날부터 자바에 남아 있던 나쁜 디자인이라고 믿습니다. JNI를 작업 할 때 문제가 있으며 byte원하는 이름을 0..255로 지정할 때 저를 믿으십시오 !
Amir Pashazadeh

답변:


92

답은 2의 보수 입니다.

간단히 말해서 Java (및 대부분의 최신 언어)는 부호있는 크기 표현을 사용하여 부호있는 정수를 나타내지 않습니다. 즉, 8 비트 정수는 부호 비트 뒤에 7 비트 부호없는 정수가 오는 것이 아닙니다.

대신 음의 정수는 2의 보수라고하는 시스템으로 표현되어 하드웨어에서 더 쉽게 산술 처리 할 수 ​​있으며 양의 0과 음의 0을 갖는 잠재적 모호성을 제거합니다. 음수 0을 제거하는 부작용은 범위 하단에 항상 하나의 추가 음수가 있다는 것입니다.

2의 보수 시스템의 또 다른 흥미로운 특성은 첫 번째 비트가 부호 표시기 (즉, 비트 1로 시작하는 모든 숫자가 음수 임)로 효과적으로 기능하지만 다음 7 비트는 자체적으로 부호없는 숫자로 해석되어서는 안된다는 것입니다. 부호 비트가 적용됩니다.

2의 보수는 그다지 복잡하지 않지만, 2의 보수가 무엇인지, 어떻게 그리고 왜 작동하는지에 대한 초기 이해를 얻는 것은 아마도 SO 답변의 범위를 벗어납니다. Wikipedia 기사로 시작하거나 더 많은 리소스에 대한 용어를 google.

-128에 대한 쿼리를 간단히 처리하기 위해 2의 보수 수를 생성하는 기본 아이디어는 숫자의 부호없는 형식을 취하고 모든 비트를 반전 한 다음 1을 더하는 것입니다. 따라서 unsigned 128은 10000000입니다. 반전하면 01111111이되고 1을 더하면 다시 10000000이됩니다. 따라서 2의 보수 시스템에서 10000000은 +128이 아니라 모호하지 않게 -128입니다. +128보다 크거나 같은 숫자는 음수의 형태로 모호하기 때문에 2의 보수 시스템을 사용하여 8 비트로 표현할 수 없습니다.


산뜻한! 그래도 맞았는지 봅시다 : 0 (00000000 제외)으로 시작하는 8 비트 숫자는 양수이고 1로 시작하는 숫자는 음수라는 것이 여전히 사실입니까? 또한 2의 보수에 대한 유일한 까다로운 점은 바이트의 비트 표현이 수학 클래스에서 수행하는 것과 동일한 값을 갖지 않는다는 것입니다. 즉, 10000000은 일반적으로 +128이지만 바이트로는 -128입니다. Amirite?
잘못된 요청

당신이 맞습니다. 첫 번째 비트는 숫자가 음수 인 경우에만 1입니다. 첫 번째 비트가 0이면 숫자는 양수 또는 0입니다.
Tyler McHenry

@Tyler : 난 당신이 아니라이 게시물 아래에 내 질문에 대답 할 수 내기 : stackoverflow.com/questions/16775169/... 나는이 너무 직선 foreward하지 희망하지만 난 정말 궁금해하고 sporadicially 난 여전히 해달라고 가지고 검색의 몇 개월 후 단서 : ~
JBA

이 코드 바이트 b1 = 0b10000000; 컴파일 오류가 발생합니까?
zeds

30

Two 's 보수는 다음과 같이 작동합니다.

바이트는 8 비트로 구성됩니다.

00000000은 0을 의미합니다.

11111111은 255를 의미합니다.

그러나 숫자가 그렇게 제시되면 결과 숫자가 양수인지 음수인지 구별하지 않습니다. 이러한 이유로 왼쪽의 비트가이 정보를 제공합니다. 왼쪽 0에있는 비트가이면 위에있는 다른 비트의 값을 추가 할 수 있습니다 zero. 비트가 1이면 위에 추가를 시작해야합니다 -128. 왼쪽에있는 비트는 2의 7 제곱이기 때문입니다.

예;

이 예에서 왼쪽의 비트는 1이며, -128의 맨 위에 다른 비트의 값을 더하고 있음을 의미합니다.

10000000 = -128 (-128 + 0)

10000001 = -127 (-128 + 1)

10000011 = -125 (-128 + 3)

10000111 = -121 (-128 + 7)

같은 비트이지만 이번에는 왼쪽의 비트가 0. 이는 우리가 위에 추가하기 시작했음을 의미 0합니다.

00000000 = 0 (0 + 0)

00000001 = 1 (0 + 1)

00000011 = 3 (0 + 3)

00000111 = 7 (0 + 7)

지금까지 괜찮다면 질문에 대한 답은

가능한 가장 작은 수

10000000 = -128

가능한 가장 큰 숫자

011111111 = 127

이것이 범위가 -128에서 127 사이 인 이유 입니다.


8

James가 그의 의견에서 지적했듯이, 그것은 2의 보수가 작동하는 방식이기 때문입니다.

다른 용어로 표현하면 2 ^ 8 = 256 종류의 값을 나타낼 수 있습니다. 즉,이 경우 128 개의 음수, 127 개의 양수 및 0으로 사용됩니다. 값을 나타 내기 위해 7 비트를 사용하고 부호에 대해 +1 비트를 사용하면 값을 하나 더 적게 나타낼 수 있고 두 개의 0도 가질 수 있습니다 (두 값을 비교하는 것이 더 복잡하기 때문에 매우 불행 할 것입니다).


3

기본 숫자 유형은 2 ^ n 숫자를 나타낼 수 있습니다. n = 2 사례를보십시오. 네 가지 경우를 나타낼 수 있으며이를 a, b, c, d라고 부릅니다. 그런 다음 a=-2, b=-1, c=0, d=1(허용되는 방식) 또는 a=-1, b=0, c=1, d=2(가능하지만 사용되지 않음 )에 동의 할 수 있습니다 . 따라서 0이 하나만 있고 2 ^ n을 유지 abs(min) != max하면 증가하는 n움직임이 테두리를 abs(min) != max유지 하지만 여전히 유지됩니다.


3

바이트는 8 비트 ---> 1 비트 부호 (양수 또는 음수) 7 비트 값으로 구성됩니다.

따라서 범위 -2 ^ 7 음수 (-128)에서 2 ^ 7 -1 양수 (127)


1

Java에서 byte short int long float double과 같은 모든 변수는 signed로 작성됩니다. 그래서 헤드 비트는 항상 (음수 또는 양수) 무엇을 지정하지만 숫자를 2로 나눌 수 있기 때문에 절반은 음수로 이동하므로 0은 기본적으로 양수입니다. 그래서 다음과 같이 보입니다.

이것은 양수
+ | 0001001
1 | 0001001
음수
-| 0001001
0 | 0001001
byte short로 음수는
-000000011111111
0000000011111111


0

2의 보수를 얻지 않고 : 2 ^ 8 (바이트는 8 자리이고 2 개의 값 중 하나를 가질 수 있기 때문에) = 256, 따라서 바이트가 나타낼 수있는 가장 개별적인 값은 256입니다. 따라서 숫자 -128에서 -1을 나타내는 것은 다음과 같습니다. 우리 범위의 절반. 여기서 질문은 왜 최대 양수 값이 128이 아니라 127이라고 믿습니다. 이것은 숫자 0을 나타내야하기 때문에 0-127은 범위의 다른 128 가능성입니다.

음수를 사용할 수없는 부호없는 바이트와 같이 양수 값만 허용했다면 범위는 0-255가 될 것입니다. 256 개의 다른 값 (0 포함)이기 때문입니다.


0

숫자에 대한 2의 칭찬을받은 후에 우리는 항상 숫자를 추가로 나타내는 한 상태를 남겼으므로 해당 상태를 -128로 바꿉니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.