ไป << และ >> ตัวดำเนินการ


124

มีใครช่วยอธิบายการใช้งาน<<และ>>ใน Go ได้ไหม ฉันเดาว่ามันคล้ายกับภาษาอื่น ๆ

คำตอบ:


170

คำจำกัดความที่เรียบง่ายยิ่งยวด (อาจจะเกิน) <<ใช้สำหรับ " >>คูณ 2" และใช้สำหรับ "หารด้วย 2" - และจำนวนหลังคือกี่ครั้ง

ดังนั้นn << xคือ "n ครั้งที่ 2, x ครั้ง" และy >> zคือ "y หารด้วย 2, z คูณ"

ตัวอย่างเช่น1 << 5"1 32 >> 5คูณ 2, 5 ครั้ง" หรือ32 และคือ "32 หารด้วย 2, 5 ครั้ง" หรือ 1

คำตอบอื่น ๆ ทั้งหมดให้คำจำกัดความทางเทคนิคมากขึ้น แต่ไม่มีใครอธิบายอย่างตรงไปตรงมาและฉันคิดว่าคุณอาจต้องการเช่นนั้น


8
นี่คือคำตอบที่ยอดเยี่ยม สิ่งนี้ทำให้มันแข็งตัวขึ้นในหัวของฉันจริงๆขอบคุณ
Sam Orozco

3
นี่คือคำตอบที่ควรจะเป็น
Utsav Gupta

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 << power = 2 ^ power)
Stephen Smith

6
ฉันคิดว่านี่จะเป็นสมการเต็มรูปแบบ: (x << n == x * 2 ^ n) (x >> n == x * 2 ^ (- n))
MondayPaper

คำตอบที่ดีฉันเปลี่ยนไบนารีในตอนแรกดูเหมือนจะลำบากในตอนแรก แต่การแปลงค่าเป็นทศนิยมด้วยพาวเวอร์เป็น 2 ช่วยได้ดี
minhajul

31

นี้ << >> และผู้ประกอบการเป็นไปเลขคณิตผู้ประกอบการ

<<   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)
    }

}

ไปสาธิต

#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's << และ >> คล้ายกับกะ (นั่นคือ: การหารหรือการคูณด้วยกำลัง 2) ในภาษาอื่น ๆ แต่เนื่องจาก Go เป็นภาษาที่ปลอดภัยกว่า C / C ++ จึงทำงานพิเศษบางอย่างเมื่อจำนวนกะเป็นตัวเลข .

คำแนะนำการเปลี่ยนในซีพียู x86 พิจารณาเพียง 5 บิต (6 บิตบนซีพียู 64 บิต x86) ของจำนวนกะ ในภาษาเช่น C / C ++ ตัวดำเนินการ shift จะแปลเป็นคำสั่ง 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 ในบริบทของซีพียูตระกูลเดียว (x86-32) ลักษณะการทำงานของคอมไพเลอร์ C / C ++ ทั้งหมด (คาดว่าจะเป็น) เหมือนกัน เหตุผลก็คือการปล่อยคำสั่ง SHL / SHR / etc 1 คำสั่งเพื่อใช้ตัวดำเนินการ shift เป็นสิ่งที่ดีที่สุดที่คอมไพเลอร์ C / C ++ ที่ปรับให้เหมาะสมสามารถทำได้เมื่อบริบทไม่ได้บอกอะไรเกี่ยวกับ 'x' และ 'y' และหากคอมไพลเลอร์ทราบข้อเท็จจริงว่าโค้ดมีลักษณะการทำงานที่ไม่ได้กำหนดก็ควรแจ้งให้ผู้ใช้ทราบ

2
ฉันไม่เห็นด้วย. คุณควรเขียนโค้ดพกพา ทั้ง Linux และ Windows ทำงานบน ARM เน้นซีพียูตระกูลเดียวคือสายตาสั้น นอกจากนี้ y ยังเป็นตัวแปร ในความเป็นจริงคอมไพเลอร์ไม่มีความรู้เกี่ยวกับค่ารันไทม์ที่แท้จริง
peterSO

@Atom นอกเหนือจากภาษาที่ไม่มีการรับประกันอย่างแน่นอนเกี่ยวกับสิ่งที่จะเกิดขึ้นพฤติกรรมที่ไม่ได้กำหนดยังมีแนวโน้มที่จะแตกต่างกันไปแม้ในเครื่องเดียวที่มีคอมไพเลอร์เดียวตัวอย่างเช่นคุณเปลี่ยนตัวเลือกการคอมไพล์ (เช่นโครงสร้างที่ปรับให้เหมาะสม) การใช้มันในทางใดทางหนึ่งถือเป็นการผิด IMO อย่างอันตราย
Paul Hankin

@ ไม่ประสงค์ออกนามใช่ แต่นั่นเป็นเพียงทฤษฎีเท่านั้น คุณสามารถให้ตัวอย่างที่เป็นรูปธรรมที่การเปลี่ยนแปลงตัวเลือกการคอมไพล์นำไปสู่พฤติกรรมที่แตกต่างกันของ<<หรือ>>ใน 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มีผลเช่นเดียวกัน เราจึงเพิ่มศูนย์ต่อท้ายหรือลบหลักสุดท้ายออก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.