>>>와 >>의 차이점


답변:


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.