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

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의 보수로 저장된다고 말합니다.



답변

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


답변

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.


답변

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

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의 보수를 사용하고있는 것 같습니다.


답변

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

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

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


답변

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


답변

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

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의 보수”는 무엇입니까?


답변

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