Java에서 정수는 내부적으로 비트 수준으로 어떻게 표현됩니까?


83

Java가 내부적으로 정수를 저장하는 방법을 이해하려고합니다. 나는 모든 자바 원시 정수가 서명된다는 것을 알고 있습니다 (짧은 것을 제외하고?). 즉, 해당 숫자에 대해 한 바이트에서 사용할 수있는 비트가 하나 적습니다.

내 질문은 모든 정수 (양수 및 음수)가 2의 보수로 저장됩니까 아니면 2의 보수에 음수 만 있습니까?

사양에 x bit two's complement number. 그러나 나는 종종 혼란스러워합니다.

예를 들면 :

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010

편집하다

확실하게, x = 15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`

따라서 답이 all숫자 라면 2의 보수로 저장됩니다.

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

여기서 다시 혼동되는 것은 둘 다 음수라는 기호입니다. 내가 잘못 읽거나 오해하고있는 것일까 요?

편집 내 질문이 헷갈리는 지 잘 모르겠습니다. 질문을 분리해야합니다.

내 질문은 정확히 : 양수 binary as is는 저장되고 음수는 저장 two's complement됩니까?

일부는 모두 2의 보수로 저장되고 하나의 대답은 음수 만 2의 보수로 저장된다고 말합니다.


2의 보수는 반드시 양수가 그 숫자의 실제 비트 값으로 표현된다는 것을 의미합니다. 적어도 내가 이해하는 한. 편집 : 또한 2의 칭찬은 기본 형식의 총 바이트 수에서 1 비트가 적다는 것을 의미하며 바이트 당 1 비트가 적다는 것을 의미합니다.
LJ2

양수와 음수는 2의 보수, 그리고 당신 : 당신의 가정이 옳다 x하고 y정확합니다.
jlordo

참고 : 인터넷 시대의 언어 인 Java가 예를 들어 표현할 데이터 유형이 없다는 것은 WTF의 무언가입니다. TCP / IP 포트 번호 (부호없는 16 비트 값)가 정확하여 때때로 코드가 정말보기 흉합니다.
hyde

위키 기사를 확인하십시오 en.wikipedia.org/wiki/… 15에 대해 제공 한 2의 보수 번호가 잘못되었습니다
Dungeon Hunter

@hyde '정말 못생긴 코드'와 같은?
Marquis of Lorne

답변:


102

Java 기본 데이터 유형을 요약하여 시작하겠습니다.

byte : Byte 데이터 유형은 부호있는 8 비트 2의 보수 정수 입니다.

Short : Short 데이터 유형은 16 비트 부호있는 2의 보수 정수 입니다.

int : Int 데이터 유형은 32 비트 부호있는 2의 보수 정수 입니다.

long : Long 데이터 유형은 64 비트 부호있는 2의 보수 정수 입니다.

float : Float 데이터 유형은 단 정밀도 32 비트 IEEE 754 부동 소수점 입니다.

double : double 데이터 유형은 배정 밀도 64 비트 IEEE 754 부동 소수점 입니다.

boolean : boolean 데이터 유형은 1 비트 정보를 나타냅니다 .

char : char 데이터 유형은 단일 16 비트 유니 코드 문자 입니다.

출처

2의 보수

"좋은 예는 256 = 255 + 1이고 (255 − x)가 x의 1의 보수라는 점에 주목함으로써 2의 보수와의 관계가 실현된다는 위키 에서 나온 것입니다.

0000 0111 = 7 2의 보수는 1111 1001 = -7

작동 방식은 MSB (최상위 비트)가 음의 값을 수신하므로 위의 경우

-7 = 1001 = -8 + 0+ 0+ 1

양의 정수는 일반적으로 간단한 이진수로 저장됩니다 (1은 1, 10은 2, 11은 3 등).

음의 정수는 절대 값의 2의 보수로 저장됩니다. 이 표기법을 사용할 때 양수의 2의 보수는 음수입니다.

출처

이 답변에 대해 몇 점을 받았으므로 더 많은 정보를 추가하기로 결정했습니다.

더 자세한 답변 :

그 중에서도 양수와 음수를 이진수로 나타내는 네 가지 주요 접근 방식이 있습니다.

  1. 부호있는 크기
  2. 하나의 보완
  3. 2의 보완
  4. 편견

1. 부호있는 크기

부호를 나타내는 데 최상위 비트를 사용하고, 나머지 비트는 절대 값을 나타내는 데 사용됩니다. 여기서 0 나타내며 양수1 나타내고 네가티브 번호 , 예를 들어 :

1011 = -3
0011 = +3

이 표현은 더 간단합니다. 그러나 십진수를 추가하는 것과 같은 방식으로 이진수를 추가 할 수 없으므로 하드웨어 수준에서 구현하기가 더 어렵습니다. 또한이 접근 방식은 0, 100 ... 0 및 0 .... 0을 나타내는 두 개의 이진 패턴을 사용합니다.

2. 하나의 보완

이 표현에서 우리는 주어진 숫자의 모든 비트를 반전하여 보완을 찾습니다. 예를 들면 :

010 = 2, so -2 = 101 (inverting all bits).

이 표현의 문제는 0 (00..0 및 11..1)을 나타내는 두 개의 비트 패턴이 여전히 존재한다는 것입니다.

3. 2의 보수

숫자의 음수를 찾기 위해이 표현에서는 모든 비트를 반전 한 다음 1 비트를 더합니다. 1 비트를 더하면 0을 나타내는 두 개의 비트 패턴이있는 문제가 해결됩니다.이 표현에서는 하나 (00 ... 0) 만 있습니다.

예를 들어, 4 비트를 사용하여 4 (십진수)의 이진 음수 표현을 찾고 싶습니다. 먼저 4를 바이너리로 변환합니다.

4 = 0100

그런 다음 모든 비트를 반전합니다.

0100 -> 1011

마지막으로 1 비트를 추가합니다.

1011 + 1 = 1100.

따라서 4 비트로 2의 보수 이진 표현을 사용하는 경우 1100은 십진수로 -4와 같습니다.

보완을 찾는 더 빠른 방법은 첫 번째 비트를 값 1로 고정하고 나머지 비트를 반전하는 것입니다. 위의 예에서는 다음과 같습니다.

0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

2의 보수 표현은 0에 대한 표현이 하나 뿐인 것 외에도 십진수와 같은 방식으로 두 개의 이진 값을 더합니다. 부호가 다른 짝수입니다. 그럼에도 불구하고 오버플로 사례를 확인해야합니다.

4. 바이어스

이 표현은 부동 소수점에 대한 IEEE 754 표준의 지수를 나타내는 데 사용됩니다. 모든 비트가 0 인 이진 값이 가장 작은 값을 나타내는 이점이 있습니다. 그리고 모든 비트가 1 인 이진 값은 가장 큰 값을 나타냅니다. 이름에서 알 수 있듯이 값은 바이어스 (일반적으로 2 ^ (n-1) 또는 2 ^ (n-1) -1)가있는 n 비트를 사용하여 이진수로 인코딩됩니다 (양수 또는 음수).

따라서 8 비트를 사용하는 경우 10 진수 값 1은 2 ^ (n-1)의 바이어스를 사용하여 이진수로 표시됩니다.

+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001

2
내 질문은 정확히 : + ve 번호는 저장되고 binary as is-ve 번호는 저장 two's complement됩니까?
Kevin Rave 2011

1
양의 정수는 일반적으로 단순 이진수로 저장되고 음의 정수는 2의 보수로 저장됩니다.
dreamcrash

제 질문에 대한 답입니다. 출처가 있습니까? 나는 이것을 명확하게 말하는 문서를 찾지 못했습니다.
Kevin Rave 2012

ecomware.com의 위 링크가 깨졌습니다 @dreamcrash, 다른 것을 제공 할 수 있습니까?
Ram Patra 2014 년

@Ramswaroop 안녕하세요, 이건
어떨까요

61

Java 정수는 32 비트이며 항상 서명됩니다. 즉, MSB (최상위 비트)가 부호 비트로 작동합니다. 로 표시되는 정수는 int비트의 가중치 합계 일뿐입니다. 가중치는 다음과 같이 지정됩니다.

Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

MSB의 가중치는 음수이므로 (실제로 가능한 가장 큰 음수)이 비트가 켜져 있으면 정수 (가중 합계)가 음수가됩니다.

4 비트 숫자로 시뮬레이션 해 보겠습니다.

Binary    Weighted sum            Integer value
0000       0 + 0 + 0 + 0           0
0001       0 + 0 + 0 + 2^0         1
0010       0 + 0 + 2^1 + 0         2
0011       0 + 0 + 2^1 + 2^0       3
0100       0 + 2^2 + 0 + 0         4
0101       0 + 2^2 + 0 + 2^0       5
0110       0 + 2^2 + 2^1 + 0       6
0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
1001      -2^3 + 0 + 0 + 2^0      -7
1010      -2^3 + 0 + 2^1 + 0      -6
1011      -2^3 + 0 + 2^1 + 2^0    -5
1100      -2^3 + 2^2 + 0 + 0      -4
1101      -2^3 + 2^2 + 0 + 2^0    -3
1110      -2^3 + 2^2 + 2^1 + 0    -2
1111      -2^3 + 2^2 + 2^1 + 2^0  -1

따라서 2의 보수는 음의 정수를 나타내는 배타적 인 체계가 아닙니다. 오히려 정수의 이진 표현이 항상 동일하다고 말할 수 있습니다. 단지 최상위 비트의 가중치를 부정합니다. 그리고 그 비트는 정수의 부호를 결정합니다.

C unsigned에는를 선언하는 데 사용할 수 있는 키워드 (자바에서는 사용할 수 없음)가 있습니다 unsigned int x;. 부호없는 정수에서 MSB의 가중치는 2^31음수가 아닌 양수 ( )입니다. 이 경우 an의 범위 unsigned int0~ 2^32 - 1이고, int범위는 -2^31~ 2^31 - 1입니다.

다른 관점에서 2의 보수 x~x + 1(NOT x + 1) 으로 고려하면 다음과 같은 설명이 있습니다.

어떤을 위해 x, ~x단지 비트 역이다 x어디든지 그래서, x1비트를 ~x해야합니다 0비트가을 (그 반대를). 따라서 이것을 더하면 더하기에 캐리가 없으며 합계는 모든 비트가 인 정수가 1됩니다.

32 비트 정수의 경우 :

x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
           = 1 0000 0000 0000 0000 0000 0000 0000 0000

가장 왼쪽 1비트는 32 비트에 맞지 않기 때문에 버려집니다 (정수 오버플로). 그래서,

x + ~x + 1 = 0
-x = ~x + 1

그래서 여러분은 음수 x가로 표현 될 수 있다는 것을 알 수 있습니다 ~x + 1. 이것은 우리가 x.


내 질문은 정확히 : + ve 번호는 저장되고 binary as is-ve 번호는 저장 two's complement됩니까?
Kevin Rave 2011

네, 그렇습니다. 음수 는 양수 값의 2의 보수로 컴퓨터에 표시 됩니다.
0605002

4
훌륭한 답변과 설명 Bonny @ 0605002, +1 :)
KM Rakibul Islam

@ 0605002 :이 답변에 대한 언급을 해주시겠습니까? 나는 개념을 알고 있었지만 그렇게 생각하지는 않았습니다. 가장 간단하고 정확한 답변.
Abhishek Singh

4 년 동안 대학 생활을했는데 2의 보완을 이해하지 못했습니다. 이 대답은 저에게 더 많은 것을 가르쳐주었습니다. 그런 단순한 것들이 전 세계적으로 그렇게 신비한 방법으로 가르치는 것은 너무 슬프다.
Prashant Pandey

10

나는 그것을 알기 위해 다음 프로그램을 실행했습니다.

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}

출력은

1010
11111111111111111111111111110110

출력에서 2의 보수를 사용하고있는 것 같습니다.


1
10의 2의 보수는 11111111 11111111 11111111 11110110. 이진수는 1010 인 동안 인쇄합니다. 따라서 -ve 숫자 만 2의 보수로 저장됩니까?
Kevin Rave 2011

위키 기사 en.wikipedia.org/wiki/를 확인하십시오. 15에 대해 제공 한 2의 보수 번호가 잘못되었습니다.
Dungeon Hunter

msb 비트가 1로 시작하면 음수가됩니다.
Dungeon Hunter

yes 2의 10의 보수는 11111111 11111111 11111111 11110110, -10입니다
Dungeon Hunter

+ 숫자 2의 보수에서 부호 비트를 떠나 바이너리로 저장됩니다했습니다
던전 헌터

4

Oracle은 흥미로울 수있는 Java 데이터 유형 에 관한 문서를 제공합니다 . 구체적으로 특별히:

int : int 데이터 유형은 32 비트 부호있는 2의 보수 정수입니다. 최소값은 -2,147,483,648이고 최대 값은 2,147,483,647 (포함)입니다.

Btw, short도 2의 보수로 저장됩니다.


3

이 문서 에 따르면 모든 정수는 Java에 대해 2의 보수 형식으로 서명되고 저장됩니다. 신뢰성이 확실하지 않습니다 ..


"2의 보수 형식에서 양수 값은 간단한 이진수로 표시됩니다." 같은 문서에 .. 그래서 기술적으로 맞습니다. :)
Shashi

3

양수는 그대로 저장 / 검색됩니다.

e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                               (0 - MSB will represent that it is +ve).
So while retrieving based on MSB; it says it is +ve, 
so the value will be taken as it is. 

그러나 음수는 2의 보수 (MSB 비트 제외) 후에 저장되고 MSB 비트는 1로 설정됩니다.

예) -10을 저장할 때

  0-000 0010  -> (1's complement) -> 0-111 1101 
              -> (2's complement) 0-111 1101 + 1 -> 0-111 1110
  Now MSB will be set to one, since it is negative no -> 1-111 1110

검색시 MSB가 1로 설정되어있는 것으로 확인되었으므로 음수 아니오입니다. 그리고 2의 보수는 MSB 이외에서 수행됩니다.

  1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
  Since MSB representing this is negative 10 --> hence  -10 will be retrived.

주조

또한 int / short를 byte로 캐스팅 할 때 마지막 바이트 만 마지막 바이트 MSB와 함께 고려됩니다.

짧게 "-130"예를 들어 보면 아래와 같이 저장 될 수 있습니다.

(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110

이제 바이트 캐스팅은 0111 1110이라는 마지막 바이트를 사용했습니다. (0-MSB) MSB가 + ve 값이라고 말 했으므로 그대로 사용됩니다. 126입니다. (+ ve).

짧게 "130"이라는 다른 예를 들어 보면 아래와 같이 저장 될 수 있습니다.

  0-000 000 1000 0010     (MSB = 0)

이제 바이트 캐스팅은 1000 0010 인 마지막 바이트를 사용했습니다. (1 = MSB) MSB가 -ve 값이라고 말 했으므로 2의 보수를 수행하고 음수를 반환합니다. 따라서이 경우 -126이 반환됩니다.

 1-000 0010  -> (1's complement) -> 1-111 1101 
             -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
               = -126

(int) (char) (byte) -1 AND (int) (short) (byte) -1 사이의 차이

(byte)-1       -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
(char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

비슷하게

(short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 

그러나

(int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
since char is unsigned; MSB won't be carry forwarded. 

(int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
since short is signed; MSB is be carry forwarded. 

참고 문헌

2의 보수가 음수를 나타내는 데 사용되는 이유는 무엇입니까?

“2의 보수”는 무엇입니까?



2

최상위 비트 (32 번째)는 숫자가 양수 또는 음수임을 나타냅니다. 0이면 숫자가 양수이고 실제 이진 표현으로 저장됨을 의미합니다. 그러나 1이면 숫자가 음수이고 2의 보수 표현에 저장됨을 의미합니다. 따라서 이진 표현에서 정수 값을 복원하면서 32 번째 비트에 가중치 -2 ^ 32를 주면 실제 답을 얻을 수 있습니다.


1
StackOverflow에 오신 것을 환영합니다! : D
0605002

2

https://stackoverflow.com/a/13422442/1065835 답변에 대한 dreamcrash 감사합니다 . 에 위키 페이지 그들은 나를 양수의 부정적인 대응의 이진 표현을 찾는 방법을 이해하는 데 도움 예를 제공합니다.

예를 들어, 1 바이트 (= 2 니블 = 8 비트)를 사용하면 10 진수 5는 다음과 같이 표시됩니다.

0000 01012 최상위 비트는 0이므로 패턴은 음이 아닌 값을 나타냅니다. 2의 보수 표기법에서 −5로 변환하기 위해 비트가 반전됩니다. 0은 1이되고 1은 0이됩니다.

1111 1010이 시점에서 숫자는 10 진수 값 −5의 1의 보수입니다. 2의 보수를 얻기 위해 결과에 1을 더하여 다음을 제공합니다.

1111 1011 결과는 2의 보수 형식으로 십진수 값 −5를 나타내는 부호있는 이진수입니다. 최상위 비트는 1이므로 표시된 값은 음수입니다.


1

양수는 이진수로 직접 저장됩니다. 음수에는 2의 칭찬이 필요합니다.

예를 들면 :

15 : 00000000 00000000 00000000 00001111
-15 : 11111111 11111111 11111111 11110001

여기에 부호있는 비트의 차이가 있습니다.


1

양의 정수 2 '의 경우 보완 값은 MSB 비트 0과 동일 (like +14 2'complement is 01110)합니다.

음의 정수에 대해서만 2'complement value를 계산합니다 (-14= 10001+1 = 10010).

따라서 최종 답변은 두 값이 모두 2 ' (+ve and -ve)보완 형식으로 만 저장된다는 것입니다.

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