มีใครช่วยอธิบายการใช้งาน<<
และ>>
ใน Go ได้ไหม ฉันเดาว่ามันคล้ายกับภาษาอื่น ๆ
มีใครช่วยอธิบายการใช้งาน<<
และ>>
ใน Go ได้ไหม ฉันเดาว่ามันคล้ายกับภาษาอื่น ๆ
คำตอบ:
คำจำกัดความที่เรียบง่ายยิ่งยวด (อาจจะเกิน) <<
ใช้สำหรับ " >>
คูณ 2" และใช้สำหรับ "หารด้วย 2" - และจำนวนหลังคือกี่ครั้ง
ดังนั้นn << x
คือ "n ครั้งที่ 2, x ครั้ง" และy >> z
คือ "y หารด้วย 2, z คูณ"
ตัวอย่างเช่น1 << 5
"1 32 >> 5
คูณ 2, 5 ครั้ง" หรือ32 และคือ "32 หารด้วย 2, 5 ครั้ง" หรือ 1
คำตอบอื่น ๆ ทั้งหมดให้คำจำกัดความทางเทคนิคมากขึ้น แต่ไม่มีใครอธิบายอย่างตรงไปตรงมาและฉันคิดว่าคุณอาจต้องการเช่นนั้น
จากข้อมูลจำเพาะที่http://golang.org/doc/go_spec.htmlดูเหมือนว่าอย่างน้อยด้วยจำนวนเต็มมันเป็นการกะไบนารี ตัวอย่างเช่นไบนารี 0b00001000 >> 1 จะเป็น 0b00000100 และ 0b00001000 << 1 จะเป็น 0b00010000
เห็นได้ชัดว่า Go ไม่ยอมรับสัญกรณ์ 0b สำหรับจำนวนเต็มไบนารี ฉันแค่ใช้มันเป็นตัวอย่าง ในเลขฐานสิบ 8 >> 1 คือ 4 และ 8 << 1 คือ 16 การเลื่อนไปทางซ้ายทีละรายการจะเหมือนกับการคูณด้วย 2 และการเลื่อนไปทางขวาจะเหมือนกับการหารด้วยสองโดยทิ้งเศษที่เหลือ
นี้ << >> และผู้ประกอบการเป็นไปเลขคณิตผู้ประกอบการ
<< left shift integer << unsigned integer
>> right shift integer >> unsigned integer
ตัวดำเนินการกะจะเลื่อนตัวถูกดำเนินการด้านซ้ายตามจำนวนกะที่ระบุโดยตัวถูกดำเนินการด้านขวา พวกเขาใช้การเลื่อนทางคณิตศาสตร์หากตัวถูกดำเนินการด้านซ้ายเป็นจำนวนเต็มที่มีการเซ็นชื่อและการเลื่อนแบบลอจิคัลหากเป็นจำนวนเต็มที่ไม่ได้ลงชื่อ จำนวนกะต้องเป็นจำนวนเต็มไม่ได้ลงชื่อ ไม่มีขีด จำกัด สูงสุดในการนับกะ การเปลี่ยนแปลงจะทำงานเหมือนกับว่าตัวถูกดำเนินการด้านซ้ายถูกเลื่อน n ครั้งโดย 1 สำหรับจำนวนกะของ n เป็นผลให้ x << 1 เท่ากับ x * 2 และ x >> 1 เหมือนกับ x / 2 แต่จะถูกตัดทอนเป็นค่าอนันต์เชิงลบ
โดยพื้นฐานแล้วมันเป็นตัวดำเนินการทางคณิตศาสตร์และในภาษาอื่น ๆ ก็เช่นกันนี่คือ 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;
}
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);
}
พวกเขาทั้งหมดจะส่งออก
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
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
<<
กะซ้าย >>
คือการเข้าสู่ระบบขยายการกะทางขวาเมื่อตัวถูกดำเนินการด้านซ้ายเป็นจำนวนเต็มที่มีการลงชื่อและเป็นตัวดำเนินการเลื่อนขวาเป็นศูนย์เมื่อตัวถูกดำเนินการด้านซ้ายเป็นจำนวนเต็มที่ไม่ได้ลงชื่อ
เพื่อให้เข้าใจถึงความ>>
คิด
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 เติมเต็ม)
ในคณิตศาสตร์ทศนิยมเมื่อเราคูณหรือหารด้วย 10เราจะส่งผลให้เลขศูนย์ต่อท้ายจำนวน
ในไบนารี , 2มีผลเช่นเดียวกัน เราจึงเพิ่มศูนย์ต่อท้ายหรือลบหลักสุดท้ายออก