>>>와 >>의 차이점


답변:


408

>>산술 시프트 오른쪽, >>>논리 시프트 오른쪽입니다.

산술 시프트에서 부호 비트는 숫자의 부호를 유지하도록 확장됩니다.

예를 들어, 8 비트로 표현 된 -2는 11111110(가장 중요한 비트는 음의 가중치를 가지므로)입니다. 산술 시프트를 사용하여 오른쪽으로 1 비트 이동하면 11111111-1이됩니다. 그러나 논리적 인 오른쪽 이동은 값이 부호있는 숫자를 나타낼 수 있다는 것을 신경 쓰지 않습니다. 단순히 모든 것을 오른쪽으로 옮기고 왼쪽에서 0으로 채 웁니다. 논리 시프트를 사용하여 -2를 1 비트 오른쪽으로 시프트하면 다음과 같이 01111111됩니다.


8
산술 시프트 사용하여 부호있는 숫자에로 곱할 있다는 데 동의하고 감사하지만 2^k, 이것이 모두의 답변이라는 것이 이상하다는 것을 알게되었습니다. 비트 열은 숫자가 아니며 >>항상 모든 비트 열에서 사용할 수 있습니다. 비트 열이 수행하는 역할과 '기호'개념이 있는지 여부에 관계없이 항상 동일한 작업을 수행합니다. 피연산자가 부호있는 숫자로 해석 되지 않는 경우에 대한 토론으로 이미 큰 대답을 확장해도 괜찮 습니까? 불만이 이해가 되나요?
Ziggy

11
왜 비트 열이 숫자가 아니라고 말합니까? 일련의 10 진수가 숫자가 아니라고 말할 수 있습니까?
danben

4
@danben 숫자인지 아닌지에 대해 논의하는 것은 문맥에 연결하는 경우에만 의미가 있습니다. 인터넷이 단지 전기라면 String은 단지 숫자라는 데 동의합니다.
bvdb

1
@danben 그러나 실제로 Ziggy가 실제로 (imho)를 참조 한 것은 a String로 간주 될 수 있다고 생각합니다 char[]. 그는 a char가 숫자가 아니라고 말하지 않고있다. 그는 단지 부호없는 숫자 라고 말하고 있습니다. 그가 잃어버린 곳이라고 생각합니다.
bvdb

5
@Ziggy가 옳음 : 모든 비트 열이 숫자는 아니며 모든 10 진수 시퀀스가 ​​숫자가 아닙니다. 예 : 전화 번호, 여러 국가의 우편 번호 등은 10 진수 문자열이지만 더하기, 빼기 또는 곱하기는 의미가 없으므로 실제로는 숫자가 아닙니다. 십진 자릿수 문자열이지만 문자열로 취급해야합니다. (캐나다와 영국의 우편 번호에는 문자와 숫자가 포함되어 있습니다.)
jcsahnwaldt는 GoFundMonica가

102

>>>부호없는 시프트입니다. 0을 삽입 >>하고 부호 비트를 확장합니다.

JLS 15.19 시프트 연산자

시프트 연산자에는 왼쪽 시프트 <<, 부호있는 오른쪽 시프트 >>및 부호없는 오른쪽 시프트가 >>>있습니다.

의 값은 부호 확장n>>s 이있는 n오른쪽으로 이동 된 s비트 위치입니다 .

의 값 n>>>s이고 n오른쪽 시프트 s와 비트 위치 제로 확장 .

    System.out.println(Integer.toBinaryString(-1));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >> 16));
    // prints "11111111111111111111111111111111"
    System.out.println(Integer.toBinaryString(-1 >>> 16));
    // prints "1111111111111111"

긍정적 인 대응 물을 더 명확하게하기 위해

System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"

양수이기 때문에 부호있는 시프트와 부호없는 시프트는 0을 가장 왼쪽 비트에 추가합니다.

관련 질문


당신의 예가 없다면, 나는 그것을 얻지 못할 것입니다.
mr5

47

그들은 둘 다 오른쪽 시프트하지만 >>>입니다unsigned

로부터 문서 :

부호없는 오른쪽 시프트 연산자 ">>>"는 0을 가장 왼쪽 위치로 이동하고 ">>"뒤의 가장 왼쪽 위치는 부호 확장에 따라 다릅니다.


12
예를 들어 설명해 주시겠습니까
Kasun Siyambalapitiya

1
나는 또한 당신이 모범을 보여야한다고 생각합니다.
byxor

나는 그것이 >>>서명되지 않았다고 생각 하지만 왜 그럴까요 7>>32=7? 나는 한 번에 한 번의 이동을 한 루프를 실행했으며 32이동 후 다시 돌아 오는 것을 보았습니다 7. 이것이 이해할 수있는 유일한 방법은 각 숫자가 바뀔 때마다 "외곽 원"에 들어갔다는 것입니다. 32교대 후 , 그것은 어떻게 든 다시 원래 위치에 도달했지만 분명히 그것은 여전히 ​​타당하지 않습니다. 무슨 일이야?
Ian Limarta 2016 년

@IanLimarta 그렇지 않습니까? 방금 0을 얻습니다. ( for (int i = 7 << 1, j = 0; j < 32; j++) System.out.println(Integer.toString(i >>= 1, 2));) >>32자체가 원래 값을 반환하는 이유를 알고 있다면 this을 참조 하십시오 .
Moira

죄송 해요. 나는 왜 '7 >>> 32 = 7'을 의미했습니다.
Ian Limarta

40

논리 오른쪽 시프트 ( v >>> n)는 비트 위치에서 비트 v가 오른쪽으로 시프트 n되고 0이 왼쪽에서 시프트 된 값을 반환합니다 . 이진수로 작성된 8 비트 값의 이동을 고려하십시오.

01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000

비트를 부호없는 음이 아닌 정수로 해석하면 논리 오른쪽 이동은 숫자를 해당하는 2의 거듭 제곱으로 나누는 효과가 있습니다. 그러나 숫자가 2의 보수 표현 인 경우 논리 오른쪽 이동은 음수를 올바르게 나누지 않습니다. . 예를 들어, 비트가 부호없는 숫자로 해석 될 때 위의 두 번째 오른쪽 이동은 128에서 32로 이동합니다. 그러나 Java에서 일반적인 것처럼 비트가 2의 보수로 해석되면 -128에서 32로 이동합니다.

따라서 2의 거듭 제곱으로 나누기 위해 이동하는 경우 산술 오른쪽 이동 ( v >> n)이 필요합니다. 비트 위치에서 비트 v가 오른쪽으로 이동 한 값을 반환하고 v의 가장 왼쪽 비트의n 사본이 왼쪽 에서 이동 된 값을 반환합니다 .

01111111 >> 2 = 00011111
10000000 >> 2 = 11100000

비트가 2의 보수 표현의 숫자 인 경우, 산술 오른쪽 시프트는 2의 거듭 제곱으로 나눠지는 효과가 있습니다. 가장 왼쪽 비트가 부호 비트이기 때문에 작동합니다. 2의 거듭 제곱으로 나누면 부호가 동일하게 유지되어야합니다.


38

>>>는 가장 왼쪽 비트에 항상 0을 >>넣고 부호의 부호에 따라 1 또는 0을 넣습니다.


10

비트 단위 및 비트 시프트 연산자 에 대해 자세히 알아보십시오

>>      Signed right shift
>>>     Unsigned right shift

비트 패턴은 왼쪽 피연산자에 의해 제공되며 오른쪽 피연산자에 의해 이동할 위치 수입니다. 부호 오른쪽 시프트 연산자 >>> 이동 제로 가장 좌측에 위치를 ,

가장 왼쪽 위치 >>는 부호 확장에 따라 다릅니다.

간단히 말해서 >>>항상 0 을 가장 왼쪽 위치로 이동시키는 반면 >>숫자의 부호를 기준으로 이동합니다. 즉 음수의 경우 1, 양수의 경우 0입니다.


예를 들어 양수뿐만 아니라 음수도 사용하십시오.

int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));

System.out.println();

c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));

산출:

11111111111111111111111111011001
11111111111111111111111101100100
  111111111111111111111111011001
11111111111111111111111101100100

                          100110
                        10011000
                          100110
                        10011000

감사. Integer.MAX_VALUE, Integer.MIN_VALUE, -1, 0, 1 의 비트 표현을 참조하기 위해 주석을 추가하고 싶습니다 . 예를 들면 : System.out.println(Integer.MAX_VALUE + ": " + String.format("%32s", Integer.toBinaryString(Integer.MAX_VALUE)).replace(' ', '0')); 정수 MAX_VALUE : 01111111111111111111111111111111; 정수 MIN_VALUE : 10000000000000000000000000000000; -1 : 11111111111111111111111111111111; 0 : 00000000000000000000000000000000; 1 : 00000000000000000000000000000001
Andy Dong

6

오른쪽 시프트 논리 연산자 ( >>> N)는 비트를 N 위치 만큼 오른쪽으로 시프트 하여 부호 비트를 버리고 N 가장 왼쪽 비트를 0으로 채 웁니다. 예를 들면 다음과 같습니다.

-1 (in 32-bit): 11111111111111111111111111111111

>>> 1작업이 된 후 :

2147483647: 01111111111111111111111111111111

오른쪽 시프트 산술 연산자 ( >> N)는 비트를 N 위치만큼 오른쪽으로 시프트하지만 부호 비트는 유지하고 N 가장 왼쪽 비트는 1로 채 웁니다. 예를 들면 다음과 같습니다.

-2 (in 32-bit): 11111111111111111111111111111110

>> 1작업이 된 후 :

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