Go << 및 >> 연산자


124

누군가가 나에게의 사용 설명시겠습니까 <<>>이동에를? 다른 언어와 비슷하다고 생각합니다.

답변:


169

슈퍼 (아마도 오버) 단순화 된 정의는 <<"2 배"에 사용되며 "2 >>로 나누기"에 사용되며 그 이후의 숫자는 몇 번입니다.

그래서 n << x"n x 2, x x"입니다. 그리고 y >> z"y를 2로 나눈 값, z 배"입니다.

예를 들어 1 << 5"1 x 2, 5 x"또는 32입니다. 그리고 32 >> 5"32를 2로 나누기, 5 x"또는 1입니다.

다른 모든 답변은 더 기술적 인 정의를 제공하지만 아무도 그것을 정말로 퉁명스럽게 배치하지 않았고 나는 당신이 그것을 원할 것이라고 생각했습니다.


7
이것은 훌륭한 대답입니다. 이것은 정말 내 머릿속을 굳혔습니다. 감사합니다.
Sam Orozco

2
이것이 답이되어야하는 방식입니다.
Utsav Gupta

103

http://golang.org/doc/go_spec.html 의 사양에서 적어도 정수의 경우 이진 시프트 인 것 같습니다. 예를 들어, 바이너리 0b00001000 >> 1은 0b00000100이고 0b00001000 << 1은 0b00010000입니다.


Go는 이진 정수에 대해 0b 표기법을 받아들이지 않는 것 같습니다. 나는 단지 예를 위해 그것을 사용하고 있었다. 십진수에서 8 >> 1은 4이고 8 << 1은 16입니다. 왼쪽으로 1만큼 이동하는 것은 2로 곱하는 것과 같고 오른쪽으로 1로 이동하는 것은 2로 나누고 나머지를 버리는 것과 같습니다.


4
좋은 대답입니다. 나는 2 (1 << 전력 = 2 ^ 전력)의 능력을 가진 코드의 거래에서 이것을 보는 것을 생각할 때 그것은 많은 이해
스티븐 스미스

6
나는 이것이 완전한 방정식이라고 생각합니다 : (x << n == x * 2 ^ n) (x >> n == x * 2 ^ (-n))
MondayPaper

좋은 답변을, 나는 이진 이동 처음에는 귀찮은 듯하지만 2 힘으로 진수 값을 변환하는 그것을 얻을 잘하는 데 도움이
minhajul을

31

<< 및 >> 연산자는 Go 산술 연산자 입니다.

<<   left shift             integer << unsigned integer
>>   right shift            integer >> unsigned integer

시프트 연산자는 오른쪽 피연산자로 지정된 시프트 카운트만큼 왼쪽 피연산자를 시프트합니다. 왼쪽 피연산자가 부호있는 정수이면 산술 시프트를 구현하고 부호없는 정수이면 논리 시프트를 구현합니다. 시프트 카운트는 부호없는 정수 여야합니다. 시프트 수에는 상한이 없습니다. 시프트는 시프트 카운트 n에 대해 왼쪽 피연산자가 1 씩 n 번 시프트 된 것처럼 작동합니다. 결과적으로 x << 1은 x * 2와 같고 x >> 1은 x / 2와 같지만 음의 무한대로 잘립니다.


10

그것들은 기본적으로 산술 연산자 이며 다른 언어에서도 마찬가지입니다. 여기에 기본 PHP, C, Go 예제가 있습니다.

가다

package main

import (
    "fmt"
)

func main() {
    var t , i uint
    t , i = 1 , 1

    for i = 1 ; i < 10 ; i++ {
        fmt.Printf("%d << %d = %d \n", t , i , t<<i)
    }


    fmt.Println()

    t = 512
    for i = 1 ; i < 10 ; i++ {
        fmt.Printf("%d >> %d = %d \n", t , i , t>>i)
    }

}

GO 데모

#include <stdio.h>
int main()
{

    int t = 1 ;
    int i = 1 ;

    for(i = 1; i < 10; i++) {
        printf("%d << %d = %d \n", t, i, t << i);
    }

        printf("\n");

    t = 512;

    for(i = 1; i < 10; i++) {
        printf("%d >> %d = %d \n", t, i, t >> i);
    }    

  return 0;
}

C 데모

PHP

$t = $i = 1;

for($i = 1; $i < 10; $i++) {
    printf("%d << %d = %d \n", $t, $i, $t << $i);
}

print PHP_EOL;

$t = 512;

for($i = 1; $i < 10; $i++) {
    printf("%d >> %d = %d \n", $t, $i, $t >> $i);
}

PHP 데모

그들은 모두 출력합니다

1 << 1 = 2 
1 << 2 = 4 
1 << 3 = 8 
1 << 4 = 16 
1 << 5 = 32 
1 << 6 = 64 
1 << 7 = 128 
1 << 8 = 256 
1 << 9 = 512 

512 >> 1 = 256 
512 >> 2 = 128 
512 >> 3 = 64 
512 >> 4 = 32 
512 >> 5 = 16 
512 >> 6 = 8 
512 >> 7 = 4 
512 >> 8 = 2 
512 >> 9 = 1 

7

Go의 << 및 >>는 다른 언어의 교대 (즉, 2의 거듭 제곱으로 나누기 또는 곱하기)와 유사하지만 Go는 C / C ++보다 안전한 언어이기 때문에 교대 횟수가 숫자 일 때 추가 작업을 수행합니다. .

x86 CPU의 시프트 명령어는 시프트 수의 5 비트 (64 비트 x86 CPU에서는 6 비트) 만 고려합니다. C / C ++와 같은 언어에서 시프트 연산자는 단일 CPU 명령어로 변환됩니다.

다음 Go 코드

x := 10
y := uint(1025)  // A big shift count
println(x >> y)
println(x << y)

인쇄물

0
0

C / C ++ 프로그램이 인쇄하는 동안

5
20

3
C 및 C ++ 시프트 연산자의 경우 "오른쪽 피연산자가 음수이거나 승격 된 왼쪽 피연산자의 비트 길이보다 크거나 같으면 동작이 정의되지 않습니다." C 및 C ++ 표준은 C 및 C ++ 프로그램이 5와 20을 인쇄한다고 보장하지 않습니다.
peterSO

@peterSO : 네, 맞아요. 내 관점은 각 프로그래밍 언어 표준이 구체적인 CPU에서 구체적인 구현을 가져야한다는 것입니다. 단일 CPU 제품군 (x86-32)의 맥락에서 모든 C / C ++ 컴파일러의 동작은 동일합니다 (예상 할 수 있음). 그 이유는 시프트 연산자를 구현하기 위해 정확히 1 개의 SHL / SHR / etc 명령어를 내보내는 것이 컨텍스트가 'x'와 'y'에 대해 아무것도 알려주지 않을 때 최적화 C / C ++ 컴파일러가 할 수있는 가장 좋은 일이기 때문입니다. 그리고 컴파일러가 코드에 정의되지 않은 동작이 있다는 사실을 알고 있다면 사용자에게이를 알려야합니다.

2
동의하지 않습니다. 이식 가능한 코드를 작성해야합니다. Linux와 Windows는 모두 ARM에서 실행됩니다. 단일 CPU 제품군에 집중하는 것은 근시안적입니다. 또한 y는 변수입니다. 사실 컴파일러는 실제 런타임 값을 알지 못합니다.
peterSO

@Atom 어떤 일이 일어날 지 전혀 보장하지 않는 언어를 제외하고, 예를 들어 컴파일 옵션 (예 : 최적화 된 빌드)을 변경하는 경우 정의되지 않은 동작은 단일 컴파일러가있는 단일 시스템에서도 달라질 수 있습니다. 어떤 식 으로든 그것에 의존 하는 것은 위험 할 정도로 잘못된 IMO입니다.
Paul Hankin

@Anonymous 예,하지만 그것은 이론 일뿐입니다. 컴파일 옵션을 변경하면 <<또는 >>C / C ++에서 다른 동작이 발생하는 구체적인 예를 제공 할 수 있습니까 ?

6

<<왼쪽 교대입니다. >>왼쪽 피연산자가 부호있는 정수이면 부호 확장 오른쪽 시프트이고 왼쪽 피연산자가 부호없는 정수이면 0 확장 오른쪽 시프트입니다.

더 잘 이해하기 위해 >>생각

var u uint32 = 0x80000000;
var i int32 = -2;

u >> 1;  // Is 0x40000000 similar to >>> in Java
i >> 1;  // Is -1 similar to >> in Java

따라서 부호없는 정수에 적용하면 왼쪽에있는 비트는 0으로 채워지고, 부호있는 정수에 적용되면 왼쪽에있는 비트는 가장 왼쪽에있는 비트로 채워집니다 (부호가있는 정수가 2에 따라 음수 일 때 1). 보어).


3

에서 소수점 수학 , 우리는 때 곱셈이나 나눗셈 (10)에 의해 , 우리는 숫자의 끝에 0을 영향을.

에서는 이진 , 2 와 동일한 효과를 갖는다. 그래서 우리는 끝에 0을 추가하거나 마지막 숫자를 제거합니다.

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