Перейдіть до операторів << і >>


124

Невже хто-небудь може пояснити мені використання <<та >>переїзд? Я думаю, це схоже на деякі інші мови.

Відповіді:


169

Супер (можливо, понад) спрощене визначення - це саме те, що <<використовується для "разів 2" і >>для "ділиться на 2" - а число після нього - скільки разів.

Так n << xсамо "n разів 2, x рази". І y >> z"y ділиться на 2, z рази".

Наприклад, 1 << 5це "1 раз 2, 5 разів" або 32. І 32 >> 5це "32, розділене на 2, 5 разів" або 1.

Усі інші відповіді дають більш технічне визначення, але ніхто не викладав це прямо, і я подумав, що ви цього хочете.


7
Це чудова відповідь. Це справді твердило це в моїй голові, дякую.
Сем Ороско

2
Ось як слід відповідати.
Уцав Гупта

103

З специфікації на http://golang.org/doc/go_spec.html , мабуть, що принаймні з цілими числами, це двійковий зсув. наприклад, двійковий 0b00001000 >> 1 буде 0b00000100, а 0b00001000 << 1 буде 0b00010000.


Очевидно, Go не приймає позначення 0b для двійкових цілих чисел. Я просто використовував це для прикладу. У десятковій формі 8 >> 1 - це 4, а 8 << 1 - 16. Переміщення вліво на одне - це те саме, що множення на 2, а зміщення праворуч на одне - це те саме, що ділення на два, відкидання будь-яких залишків.


4
Чудова відповідь. Це має багато сенсу, коли я думаю, що я бачив це в коді, що стосується повноважень 2 (1 << потужність = 2 ^ потужність)
Стівен Сміт

6
Я думаю, що це було б повне рівняння: (x << n == x * 2 ^ n) (x >> n == x * 2 ^ (- n))
понеділокПеред

приємна відповідь, я спочатку двійковим зміщенням здавався
клопітким,

31

Оператори << і >> - це оператори Go Arithmetic .

<<   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 Example

ПЕРЕГЛЯД

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 Demo

С

#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 враховують лише 5 біт (6 біт на 64-бітних процесорах x86) підрахунку зміни. У таких мовах, як C / C ++, оператор зміни перекладається на єдину інструкцію процесора.

Наступний код 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: Так, ти маєш рацію. Моя точка зору полягає в тому, що кожен стандарт мови програмування повинен мати конкретну реалізацію на конкретному процесорі. У контексті однієї сімейства процесорів (x86-32) поведінка всіх компіляторів C / C ++ є (можна очікувати, є) однаковою. Причиною цього є те, що видавати рівно 1 інструкцію SHL / SHR / тощо для реалізації оператора зсуву - це найкраще, що може зробити оптимізаційний компілятор C / C ++, коли контекст нічого не говорить про "x" та "y". І якщо компілятор напевно знає, що код має невизначену поведінку, він повинен повідомити про це користувача.

2
Я не погоджуюсь. Вам слід написати портативний код. І Linux, і Windows працюють на ARM. Зосередження уваги на одній родині процесорів короткозорі. Також y - змінна. Фактично, компілятор не знає його фактичних значень часу виконання.
peterSO

@Atom Окрім мови, яка не надає абсолютно ніяких гарантій щодо того, що буде, не визначена поведінка може змінюватися навіть на одній машині з одним компілятором, якщо, наприклад, ви змінюєте параметри компіляції (наприклад, оптимізована збірка). Покладатися на нього будь-яким чином небезпечно неправильно ІМО.
Пол Ханкін

@Anonymous Так, але це лише теорія. Чи можете ви навести конкретний приклад, коли зміна параметрів компіляції призводить до різної поведінки <<або >>на C / C ++?

6

<<ліва зміна. >>- правий зсув, що розширюється за знаками, коли лівий операнд є цілим числом, що підписується, і правий зсув правого зсуву, коли лівий операнд є цілим числом, яке не підписується.

Щоб краще зрозуміти, >>подумайте

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

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

Отже, застосовуючи до непідписаного цілого числа, біти зліва заповнюються нулем, тоді як при застосуванні до підписаного цілого числа біти зліва заповнюються самим крайнім лівим бітом (що дорівнює 1, коли підписане ціле число від'ємне як у 2-х доповнення).


3

У десятковій математиці , коли множимо чи ділимо на 10 , нулі на кінець числа.

У довічним , 2 мають той же ефект. Тому ми додаємо нуль до кінця або видаляємо останню цифру

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.