โปรแกรมเมอร์ที่มีความรอบรู้ดีแค่ไหนที่จะต้องมีการดำเนินการที่ชาญฉลาด? [ปิด]


34

ฉันได้รับการเรียกดูรหัส OpenJDK บางเมื่อเร็ว ๆ นี้และได้พบบางอย่างที่น่าสนใจชิ้นส่วนของรหัสมีที่จะทำอย่างไรกับการดำเนินงานบิตที่ชาญฉลาด ฉันยังถามคำถามเกี่ยวกับ StackOverflow

อีกตัวอย่างที่แสดงให้เห็นถึงจุด:

 1141       public static int bitCount(int i) {
 1142           // HD, Figure 5-2
 1143           i = i - ((i >>> 1) & 0x55555555);
 1144           i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
 1145           i = (i + (i >>> 4)) & 0x0f0f0f0f;
 1146           i = i + (i >>> 8);
 1147           i = i + (i >>> 16);
 1148           return i & 0x3f;
 1149       }

รหัสนี้สามารถพบได้ในชั้นเรียนจำนวนเต็ม

ฉันอดไม่ได้ที่จะรู้สึกงี่เง่าเมื่อฉันมองสิ่งนี้ ฉันพลาดชั้นเรียนหรือสองในวิทยาลัยหรือนี่ไม่ใช่สิ่งที่ฉันควรจะได้รับหรือไม่? ฉันสามารถดำเนินการ bit-wise แบบง่าย ๆ (เช่น ANDing, ORing, XORing, shifting) แต่มาเลยคนที่มาด้วยรหัสแบบนั้นได้อย่างไร

โปรแกรมเมอร์ที่มีความรอบรู้ดีแค่ไหนที่จะต้องมีการดำเนินการที่ชาญฉลาด?

ในหมายเหตุด้านข้าง ... สิ่งที่ฉันกังวลคือคนที่ตอบคำถามของฉันใน StackOverflow ตอบคำถามนั้นในเวลาไม่กี่นาที ถ้าเขาทำได้อย่างนั้นทำไมฉันถึงจ้องเหมือนกวางที่อยู่บนไฟหน้า?


4
คุณทำงานด้านการพัฒนาประเภทใด (หรือต้องการทำในตอนนี้ถ้าคุณไม่ทำ) ฉันไม่เห็นว่าสิ่งนี้มีประโยชน์ในการพัฒนาเว็บ แต่ฉันเห็นการทำงานระดับบิตจำนวนมากในระบบฝังตัวทำงาน
โธมัสโอเวนส์

26
ถ้าฉันจ้างคนให้ทำส่วนต่อประสานกับผู้ใช้หรือการพัฒนาเว็บการจัดการบิตไม่ใช่สิ่งที่ฉันถามเพราะมีโอกาสพวกเขาจะไม่เห็นมัน อย่างไรก็ตามฉันคาดหวังว่าคนที่ทำงานกับโปรโตคอลเครือข่ายระบบฝังตัวและไดรเวอร์อุปกรณ์ทำงานได้คุ้นเคยกับมัน
โธมัสโอเวนส์

11
อะไรในโลก>>>ในฐานะผู้ดำเนินการ
DeadMG

10
@DeadMG: กะขวาที่ไม่ได้ลงชื่อ download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
c_maker

3
// HD, Figure 5-2จะเป็นสิ่งแรกที่ฉันได้ดู ตามความเห็นที่จุดเริ่มต้นของไฟล์ที่เป็นHD Henry S. Warren, Jr.'s Hacker's Delight
schnaader

คำตอบ:


38

ฉันจะบอกว่าเป็นนักพัฒนาที่รอบรู้คุณต้องเข้าใจผู้ประกอบการและการดำเนินงานระดับบิต

อย่างน้อยที่สุดคุณควรจะสามารถคิดรหัสข้างบนได้หลังจากที่คิดไปเล็กน้อย

การใช้งานระดับบิตมีแนวโน้มค่อนข้างต่ำดังนั้นหากคุณทำงานกับเว็บไซต์และซอฟต์แวร์ LOB คุณจะไม่ใช้มันมากนัก

เช่นเดียวกับสิ่งอื่น ๆ ถ้าคุณไม่ใช้มันมากคุณจะไม่คุ้นเคยกับมัน

ดังนั้นคุณไม่ควรกังวลกับคนที่สามารถคิดออกได้อย่างรวดเร็วเนื่องจากพวกเขา (อาจ) ทำงานกับโค้ดประเภทนี้มาก อาจจะเขียนรหัส OS, รหัสไดรเวอร์หรือการจัดการบิตอื่น ๆ ที่ยุ่งยาก


1
+1: การใช้งาน Bitwise เป็นบิตของความรู้ที่สำคัญ (ไม่มีการเล่นสำนวน) สำหรับนักพัฒนา แต่พวกเขาเท่านั้นที่สำคัญจริง ๆในสถานการณ์เฉพาะตอนนี้ หากคุณไม่เคยเจอพวกเขาในแบบวันต่อวันการมีความรู้ทั่วไปนั้นดีกว่าการทารุณพวกเขา ทำให้พื้นที่สมองนั้นว่าง
Nicholas Smith

คุณควรเข้าใจเมื่อคุณจะใช้พวกเขาและไม่ต้องอายที่จะใช้มันหากพวกเขาเป็นทางออกที่ถูกต้องสำหรับปัญหาที่เกิดขึ้น
user606723

เพื่อเพิ่มความคิดเห็นของ @ user606723 - มีเพียงไม่กี่แห่งที่มักใช้สิ่งที่บิตและมักจะพบมากหรือน้อย - hashing (และสิ่งที่เกี่ยวข้องกับมัน) และการแยก / การตั้งค่าสี RGB เฉพาะถ้าพวกเขา int'ใหม่เก็บไว้ใน เช่นข้อมูล CPU สามารถอ่านได้โดยตรวจสอบค่าสถานะบิตที่ส่งคืนจากรีจิสเตอร์ที่ระบุ
TC1

36

หากคุณเข้าใจวิธีแก้ปัญหาเช่น "กำหนดว่าจะตั้งบิต 3 และ 8 ไว้หรือไม่" ล้างบิต 5 "หรือ" หาค่าจำนวนเต็มที่แทนด้วยบิต 7-12 "คุณมีความเข้าใจเพียงพอของผู้ประกอบการระดับบิตเพื่อตรวจสอบกระป๋องกล่องTwiddle Bitsในรายการตรวจสอบ "รอบรู้"

ตัวอย่างของคุณมีอะไรบ้างมาจากแฮ็คเกอร์ดีไลท์การรวบรวมอัลกอริธึมประสิทธิภาพสูงสำหรับจัดการข้อมูลขนาดเล็กเช่นจำนวนเต็ม ใครก็ตามที่เขียนรหัสนั้นในตอนแรกไม่เพียง แต่คายมันออกมาในห้านาที เรื่องราวเบื้องหลังมีแนวโน้มว่าจะมีความต้องการวิธีที่รวดเร็วและไม่มีสาขาในการนับบิตและผู้เขียนมีเวลาที่จะจ้องมองที่สตริงของบิตและทำอาหารขึ้นมาเพื่อแก้ปัญหา ไม่มีใครจะเข้าใจว่ามันทำงานอย่างไรได้อย่างรวดเร็วเว้นแต่พวกเขาเคยเห็นมาก่อน ด้วยความเข้าใจอย่างถ่องแท้เกี่ยวกับข้อมูลเบื้องต้นระดับบิตและเวลาที่ใช้ในการทดสอบโค้ดคุณอาจจะทราบได้ว่ามันทำงานอย่างไร

แม้ว่าคุณจะไม่เข้าใจอัลกอริธึมเหล่านี้ แต่การรู้ว่ามันมีอยู่นั้นเพิ่มให้กับ "ความกลม" ของคุณเพราะเมื่อถึงเวลาจัดการพูดการนับบิตประสิทธิภาพสูงคุณรู้ว่าต้องเรียนอะไร ในโลกก่อนยุคของ Google มันเป็นเรื่องยากมากที่จะรู้เกี่ยวกับสิ่งเหล่านี้ ตอนนี้มันกดแป้นไป

ผู้ใช้ที่ตอบคำถาม SO ของคุณอาจเคยเห็นปัญหามาก่อนหรือเรียนรู้การแฮ็ก เขียนเขาและถาม


+1 อย่างน้อยก็รับรู้สิ่งเหล่านี้ มันเป็นเรื่องดีที่จะรู้อะไรสักอย่างเกี่ยวกับเรื่องนี้มากมาย ถ้าคนในอุตสาหกรรมเริ่มพูดถึงเรื่องแบบนี้คุณไม่อยากเป็นคนที่อยู่ในห้องที่ไม่ค่อยมีเงื่อนงำอะไรที่จะพูดถึง
maple_shaft

3
+1 สำหรับการแก้ไขตัวย่อ "HD" ในความคิดเห็นของรหัสด้านบน
PéterTörök

ฉันชอบของประเภทนี้และเพิ่งสั่งซื้อหนังสือ HD ขอบคุณสำหรับการอ้างอิง
tcrosley

8

จากตัวอย่างของคุณมีบางสิ่งที่คุณควรรู้อย่างแน่นอนโดยไม่คิดจริงๆ

1143 i = i - ((i >>> 1) & 0x55555555);

คุณควรรู้จักรูปแบบบิต 0x555 ... เป็นรูปแบบบิตที่สลับกัน 0101 0101 0101 และตัวดำเนินการถูกชดเชยด้วย 1 บิต (ไปทางขวา) และนั่นคือการดำเนินการปิดบัง (และความหมายของการปิดบัง)

1144 i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

อีกรูปแบบหนึ่งอันนี้คือ 0011 0011 0011 นอกจากนี้มันเปลี่ยนสองครั้งแล้วปิดบังอีกครั้ง การเลื่อนและปิดบังเป็นไปตามรูปแบบที่คุณควรจดจำ ...

1145 i = (i + (i >>> 4)) & 0x0f0f0f0f;

รูปแบบแข็งตัว ครั้งนี้เป็น 00001111 00001111 และแน่นอนเราจะเลื่อน 4 ครั้งนี้ ทุกครั้งที่เราขยับตามขนาดของหน้ากาก

1148 ส่งคืนฉัน & 0x3f;

อีกรูปแบบบิต 3f คือบล็อกของศูนย์ตามด้วยบล็อกที่ใหญ่กว่า

ทุกสิ่งเหล่านี้ควรจะชัดเจนในทันทีถ้าคุณ "รอบดี" แม้ว่าคุณจะไม่เคยคิดว่าคุณจะใช้มันคุณอาจจะพลาดโอกาสในการทำให้โค้ดของคุณง่ายขึ้นอย่างมากหากคุณไม่ทราบสิ่งนี้

แม้ในภาษาระดับสูงกว่าบิต patters ใช้ในการจัดเก็บข้อมูลจำนวนมากในเขตข้อมูลขนาดเล็ก นี่คือเหตุผลที่คุณเห็นข้อ จำกัด ของ 127/8, 63/4 และ 255/6 เสมอในเกมเพราะคุณต้องเก็บสิ่งต่าง ๆ เหล่านี้ไว้มากมายโดยไม่ต้องบรรจุฟิลด์คุณจะถูกบังคับให้ใช้มากถึงสิบเท่า จำนวนหน่วยความจำ (สิ่งที่ดีที่สุดคือถ้าคุณต้องการเก็บบูลีนจำนวนมากในอาเรย์คุณสามารถประหยัดหน่วยความจำได้ 32-64 เท่าของจำนวนหน่วยความจำที่คุณจะใช้ถ้าคุณไม่ได้คิดถึงมัน - ภาษาส่วนใหญ่ใช้บูลีนเป็น คำที่มักจะเป็น 32 บิตผู้ที่ไม่รู้สึกสะดวกสบายในระดับนี้จะต่อต้านโอกาสในการจัดเก็บข้อมูลเช่นนี้เพียงเพราะกลัวสิ่งที่ไม่รู้จัก

พวกเขาจะอายห่างจากสิ่งต่าง ๆ เช่นแพ็คเก็ตการแจงด้วยตนเองที่ส่งผ่านเครือข่ายในรูปแบบที่อัดแน่น - สิ่งที่ไม่สำคัญหากคุณไม่กลัว สิ่งนี้อาจทำให้เกมต้องใช้แพ็คเก็ตขนาด 1k ลงถึงต้องใช้ 200 ไบต์แพ็คเก็ตขนาดเล็กจะเลื่อนผ่านเครือข่ายได้อย่างมีประสิทธิภาพมากขึ้นและลดเวลาหน่วงและเปิดใช้งานความเร็วในการโต้ตอบสูงขึ้น


5

ฉันเคยรู้จักรหัสเพราะฉันเคยเห็นมาก่อนในซอฟต์แวร์สำหรับจัดการเฟรมวิดีโอ หากคุณทำงานกับสิ่งต่างๆเช่น CODEC ระบบเสียงและวิดีโอโปรโตคอลเครือข่ายหรือการลงทะเบียนชิปคุณจะเห็นการทำงานระดับบิตจำนวนมากและมันจะกลายเป็นเรื่องที่สองสำหรับคุณ

คุณไม่ควรรู้สึกแย่ถ้างานของคุณเกิดขึ้นไม่ตรงกับโดเมนเหล่านั้นบ่อยนัก ฉันรู้ว่าการทำงานระดับบิตอัพดี แต่ฉันช้าลงในโอกาสที่หายากที่ฉันต้องเขียน GUI เพราะนิสัยใจคอทั้งหมดที่มีเลย์เอาต์และการถ่วงน้ำหนักและการขยายตัวและนั่นเป็นเรื่องที่สอง จุดแข็งของคุณคือทุกที่ที่คุณมีประสบการณ์มากที่สุด


4

สิ่งสำคัญที่คุณควรระวังคือวิธีการแสดงจำนวนเต็ม (โดยทั่วไปบิตบิตเตอร์คงที่ที่ความยาวขึ้นอยู่กับแพลตฟอร์ม) และการดำเนินการที่มีอยู่ในนั้น

การดำเนินการทางคณิตศาสตร์หลัก+ - * / %สามารถเข้าใจได้โดยไม่จำเป็นต้องเข้าใจแม้ว่ามันจะมีประโยชน์สำหรับการปรับให้เหมาะสมแบบไมโคร (แม้ว่าส่วนใหญ่แล้วคอมไพเลอร์จะสามารถดูแลคุณได้)

ชุดการจัดการบิต| & ~ ^ << >> >>>ต้องมีความเข้าใจอย่างน้อยเพื่อให้สามารถใช้งานได้

อย่างไรก็ตามเวลาส่วนใหญ่คุณจะใช้พวกเขาเพื่อส่งบิตแฟล็กไปยังวิธีการORรวมเข้าด้วยกันและส่งผ่าน int จากนั้นANDทำการตั้งค่าสามารถอ่านได้มากกว่าการผ่านบูลีน (มากถึง 32) หลายรายการในรายการพารามิเตอร์แบบยาวและอนุญาต แฟล็กที่เป็นไปได้ที่จะเปลี่ยนโดยไม่เปลี่ยนอินเตอร์เฟส

ไม่ต้องพูดถึง booleans โดยทั่วไปแล้วจะเก็บแยกเป็นไบต์หรือ ints แทนการรวมเข้าด้วยกันเหมือนธง


สำหรับส่วนของโค้ดมันจะนับจำนวนขนานของบิตนี้ทำให้อัลกอริทึมทำงานในO(log(n))กรณีที่ n คือจำนวนบิตแทนที่จะเป็นวงไร้เดียงสาซึ่งเป็นO(n)

ขั้นตอนแรกคือยากที่จะเข้าใจ แต่ถ้าคุณเริ่มต้นจากการตั้งค่าที่จะมีการเปลี่ยนลำดับบิต0b00ไป0b00, 0b01ไป0b01, 0b10ไป0b01และ0b11เพื่อให้0b10มันกลายเป็นเรื่องง่ายที่จะปฏิบัติตาม

ดังนั้นสำหรับขั้นตอนแรกi - ((i >>> 1) & 0x55555555)ถ้าเราทำiอย่าง0b00_01_10_11นั้นให้ได้ผลลัพธ์ที่ควรจะเป็น0b00_01_01_10

(โปรดทราบว่า0x5มีค่าเท่ากับ0b0101)

ไอยูเอฟเราใช้ i = 0b00_01_10_11ที่นี้หมายถึงว่า0b00_01_01_10 - (0b00_00_11_01 & 0b01_01_01_01)เป็น0b00_01_10_11 - 0b00_00_01_01ซึ่งจะกลายเป็น0b00_01_01_10

พวกเขาสามารถทำได้(i & 0x55555555) + ((i >>> 1) & 0x55555555)เพื่อผลลัพธ์เดียวกัน แต่นี่เป็นการดำเนินการเพิ่มเติม 1 รายการ

ขั้นตอนต่อไปนี้อยู่ในหลอดเลือดดำที่คล้ายกัน


4
คุณภาพที่สำคัญที่สุดของรหัสนี้คือมันเป็นสาขาฟรีซึ่งอาจให้ประโยชน์มากกว่าการลดความซับซ้อน
Simon Richter

3

ทุกคนควรเข้าใจการทำงานระดับบิตขั้นพื้นฐาน มันเป็นองค์ประกอบของการดำเนินงานขั้นพื้นฐานในการปฏิบัติงานด้วยวิธีที่เหมาะสมและมีประสิทธิภาพที่ต้องใช้เวลาในการฝึกฝนมากมาย

ผู้ที่ทำงานกับการจัดการบิตทุกวัน (เช่นคนที่ฝังตัว) คือแน่นอนว่าจะพัฒนาสัญชาตญาณที่แข็งแกร่งและเทคนิคที่ดี

โปรแกรมเมอร์ที่ไม่ได้ทำสิ่งที่มีทักษะระดับต่ำควรมีทักษะมากน้อยเพียงใดด้วยการจัดการที่ชาญฉลาด? พอที่จะนั่งลงด้วยบทบาทเช่นคุณวางและทำงานอย่างช้า ๆ ราวกับว่ามันเป็นเกมพัฒนาสมองหรือปริศนา

ด้วยโทเค็นเดียวกันฉันจะบอกว่าโปรแกรมเมอร์ที่ฝังตัวควรเข้าใจ HTTP มากพอ ๆ กับที่นักพัฒนาเว็บเข้าใจเกี่ยวกับการจัดการบิตที่ชาญฉลาด กล่าวอีกนัยหนึ่งก็คือ "ตกลง" ที่จะไม่หวือหวาเลยแม้แต่น้อยหากคุณไม่ได้ใช้มันตลอดเวลา


3
ที่จริงแล้วในบางกรณีโปรแกรมเมอร์ฝังตัวต้องเข้าใจเกี่ยวกับ http มากกว่านักพัฒนาเว็บ (ฉันทำทั้งสองอย่าง) ในการพัฒนาเว็บไซต์คุณสามารถพึ่งพากรอบงานบางประเภทได้ ในฐานะนักพัฒนาสมองกลฝังตัวที่ทำงานกับอุปกรณ์ที่เชื่อมต่ออินเทอร์เน็ตฉันจึงต้องเขียนโค้ด http stack ตั้งแต่เริ่มต้น
tcrosley

@tcrosely ใช่คุณถูกต้องแน่นอน บางทีตัวอย่างที่ดีกว่า "http" น่าจะเป็น "ORM" หรือ "JEE" ประเด็นหลักคือคนทั่วไปไม่สามารถมีความเชี่ยวชาญในบางประเด็นเว้นแต่ว่าพวกเขาจะฝึกฝนอย่างสม่ำเสมอ
Angelo

ฉันเห็นด้วยและฉันไม่เคยจัดการกับ ORM หรือ JEE (เพียงแค่ JME ย้อนกลับเมื่อมันถูกเรียกว่า J2ME)
tcrosley

3

ความสุขของแฮ็กเกอร์เป็นงานที่มา บรรพบุรุษของทั้งหมดคือ HakMem ตั้งแต่ปี 1972 http://w3.pppl.gov/~Hammett/work/2009/AIM-239-ocr.pdf

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


นอกจากนี้ยังมีรุ่น HTML HAKMEM ดูรายการ 169
Mackie Messer

3

ผู้ประกอบการระดับบิตตีความยากแค่ไหน

ฉันตั้งโปรแกรมระบบฝังตัว ฉันฝึกฝนสิ่งนี้มามาก คำถามที่เชื่อมโยงของคุณเกี่ยวกับแผนที่แฮชพร้อมรหัส

static int hash(int h) {
   // This function ensures that hashCodes that differ only by
   // constant multiples at each bit position have a bounded
   // number of collisions (approximately 8 at default load factor).
   h ^= (h >>> 20) ^ (h >>> 12);
   return h ^ (h >>> 7) ^ (h >>> 4);
}

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

การสร้างความแตกต่างระหว่างการอ่านและการทำความเข้าใจรหัสเป็นสิ่งสำคัญ ฉันสามารถตีความbitCountรหัสและอ่านสิ่งที่มันทำ แต่พิสูจน์ว่าทำไมมันทำงานหรือแม้กระทั่งว่ามันจะใช้เวลาสักครู่ มีความแตกต่างระหว่างความสามารถในการอ่านโค้ดได้อย่างราบรื่นและความสามารถในการอ่านว่าทำไมโค้ดถึงเป็นแบบนั้น อัลกอริทึมบางอย่างนั้นยาก สิ่งที่ของhashความรู้สึกรหัสทำ แต่ความคิดเห็นอธิบายว่าทำไมสิ่งที่กำลังทำ อย่าท้อแท้ถ้าฟังก์ชั่นที่ใช้ตัวดำเนินการบิตเข้าใจยากพวกเขามักจะใช้ในการทำสิ่งที่ยุ่งยากทางคณิตศาสตร์ซึ่งจะยากไม่ว่ารูปแบบ

อุปมา

ฉันคุ้นเคยกับสิ่งนี้ วิชาหนึ่งที่ฉันไม่คุ้นเคยคือregex ฉันจัดการกับพวกเขาเป็นครั้งคราวในการสร้างสคริปต์ แต่ไม่เคยทำงานพัฒนารายวัน

ฉันรู้วิธีใช้องค์ประกอบต่อไปนี้ของ regex:

  • [] คลาสของอักขระ
  • *, .และ+สัญลักษณ์
  • จุดเริ่มต้นของสตริง^และจุดสิ้นสุดของสตริง$
  • คลาสอักขระ \ d, \ w และ \ s
  • แฟล็ก / g

นี่เพียงพอที่จะสร้างคิวรีแบบง่ายและแบบสอบถามจำนวนมากที่ฉันเห็นไม่หลงทางจากจุดนี้

อะไรก็ตามที่ไม่อยู่ในรายการนี้ฉันไปถึงแผ่นโกง อะไรก็ตามยกเว้น{}และ()- แผ่นโกงจะไม่เพียงพอ ฉันรู้เพียงพอเกี่ยวกับคนเหล่านี้ที่จะรู้ว่าฉันจะต้องมีไวท์บอร์ดคู่มืออ้างอิงและอาจเป็นเพื่อนร่วมงาน คุณสามารถบรรจุอัลกอริธึมบ้า ๆ ไว้ใน regex สั้น ๆ สองสามบรรทัด

ในการออกแบบ regex ที่ต้องการหรือแนะนำอะไรที่ไม่ได้อยู่ในรายการองค์ประกอบที่รู้จักของฉันฉันจะแสดงรายการคลาสทั้งหมดของอินพุตที่ฉันคาดว่าจะรับรู้และใส่ไว้ในชุดทดสอบ ฉันจะสร้าง regex อย่างช้าๆและเพิ่มขึ้นมีขั้นตอนเป็นระยะ ๆ และทำตามขั้นตอนเหล่านี้เพื่อควบคุมแหล่งที่มาและ / หรือทิ้งไว้ในความคิดเห็นเพื่อให้ฉันสามารถเข้าใจสิ่งที่ควรจะเกิดขึ้นในภายหลังเมื่อแบ่ง หากอยู่ในรหัสการผลิตฉันจะทำให้แน่ใจว่าจะได้รับการตรวจสอบโดยผู้ที่มีประสบการณ์มากกว่า

นี่คือที่ที่คุณอยู่กับผู้ประกอบการระดับบิต?

ดังนั้นคุณต้องการที่จะโค้งมนอย่างดี?

ในการประมาณของฉันถ้าคุณสามารถตีความรหัสเช่นนี้ทำได้โดยการดึงกระดาษออกมาหรือไปที่ไวท์บอร์ดและวิ่งผ่านการปฏิบัติการด้วยตนเองคุณจะมีคุณสมบัติกลมกลืน หากต้องการมีคุณสมบัติเป็นโปรแกรมเมอร์ที่มีความรอบรู้ในด้านการดำเนินงานระดับบิตคุณควรจะสามารถทำสี่สิ่งต่อไปนี้:

  1. สามารถอ่านและเขียนการดำเนินงานทั่วไปได้อย่างคล่องแคล่ว
    สำหรับโปรแกรมเมอร์แอปพลิเคชันการดำเนินการทั่วไปที่มีตัวดำเนินการระดับบิตรวมถึงตัวดำเนินการพื้นฐานของ|และ&เพื่อตั้งค่าและล้างค่าสถานะ มันควรจะง่าย คุณควรจะสามารถอ่านและเขียนสิ่งที่ชอบ

    open('file', O_WRONLY | O_APPEND | O_CREAT );
    // Use an OR operator ^ here and ^ here to set multiple flags
    

    โดยไม่ทำให้ช้าลง (สมมติว่าคุณรู้ว่าธงหมายถึงอะไร )

  2. สามารถอ่านดำเนินงานที่ซับซ้อนมากขึ้นด้วยการทำงานบางอย่าง
    บิตนับได้อย่างรวดเร็วจริงๆใน O (เข้าสู่ระบบ (n)) เวลาโดยไม่ต้องสาขาเพื่อให้มั่นใจว่าจำนวนของการชนกันใน hashcodes อาจแตกต่างกันตามจำนวนเงินที่ จำกัด และแยกที่อยู่อีเมล , หมายเลขโทรศัพท์หรือHTML ที่มี regex เป็นปัญหาที่ยาก มันสมเหตุสมผลสำหรับทุกคนที่ไม่ใช่ผู้เชี่ยวชาญในพื้นที่เหล่านี้เพื่อเข้าถึงไวท์บอร์ดมันไม่มีเหตุผลที่จะไม่สามารถเริ่มทำงานเพื่อทำความเข้าใจ

  3. สามารถเขียนอัลกอริทึมที่ซับซ้อนด้วยการทำงานจำนวนมาก
    หากคุณไม่ใช่ผู้เชี่ยวชาญคุณไม่ควรคาดหวังที่จะทำสิ่งที่ซับซ้อนและยาก อย่างไรก็ตามโปรแกรมเมอร์ที่ดีควรจะสามารถทำได้โดยทำงานอย่างต่อเนื่อง ทำสิ่งนี้ให้เพียงพอและในไม่ช้าคุณจะเป็นผู้เชี่ยวชาญ :)


2

หากคุณไปเรียนต่อในมหาวิทยาลัยที่ดีคุณจะต้องเข้าเรียนคณิตศาสตร์ไม่ต่อเนื่อง คุณจะได้เรียนรู้เลขคณิตเลขฐานสองและเลขฐานสิบหกและประตูตรรกะ

ในบันทึกนั้นมันเป็นเรื่องปกติที่จะรู้สึกสับสนถ้าหากคุณเป็นปลอบใจคุณตั้งแต่ฉันเขียนเว็บแอพพลิเคชั่นฉันไม่จำเป็นต้องดูหรือเขียนโค้ดแบบนี้ แต่เนื่องจากฉันเข้าใจเลขคณิตไบนารีและพฤติกรรมของผู้ประกอบการบิต ในที่สุดฉันก็สามารถหาสิ่งที่เกิดขึ้นที่นี่ให้เวลาเพียงพอ


2

ในฐานะโปรแกรมเมอร์ของโทรศัพท์มือถือฉันต้องจัดการกับเรื่องแบบนี้ เป็นเรื่องปกติพอสมควรที่อุปกรณ์มีหน่วยความจำไม่มากหรือความเร็วในการส่งข้อมูลมีความสำคัญ ในทั้งสองกรณีคุณพยายามที่จะแพ็คข้อมูลให้มากที่สุดเท่าที่เป็นไปได้ในไม่กี่ไบต์

ฉันจำไม่ได้ว่าใช้ตัวดำเนินการ bitwise ใน 5 ปีหรือมากกว่านั้นของ PHP (อาจเป็นเพียงฉัน) ไม่ใช่ใน 10 ปีหรือมากกว่านั้นในการเขียนโปรแกรม Windows แม้ว่าจะมีบางสิ่งที่ Windows ระดับต่ำกว่าจะแพ็คบิตก็ตาม

คุณพูดว่า "ฉันอดไม่ได้ที่จะรู้สึกงี่เง่าเมื่อฉันมองสิ่งนี้" อย่า - รู้สึกโกรธ

คุณเพิ่งได้พบกับผลลัพธ์ของโปรแกรมเมอร์โคบาล

เขาไม่รู้อะไรเลยในการเขียนรหัสที่สามารถบำรุงรักษาได้หรือไม่? ฉันหวังเป็นอย่างยิ่งว่าเขาจะเป็นคนที่ต้องกลับมาที่นี่ในอีกหนึ่งปีและลองและจดจำความหมายของมัน

ฉันไม่ทราบว่าคุณตัดความคิดเห็นหรือไม่มี แต่รหัสนี้จะไม่ผ่านการตรวจสอบรหัสที่ฉันเป็นผู้จัดการ QA s / w (และฉันได้ไม่กี่ครั้ง)

นี่คือกฎที่ดีของหัวแม่มือ - ที่ "จำนวนเต็มเปล่า" เท่านั้นที่ได้รับอนุญาตในรหัส 0 1ND 1. ทุกหมายเลขอื่น ๆ ที่ควรจะเป็น # กำหนดค่าใช้จ่าย enums ฯลฯ ขึ้นอยู่กับภาษาของคุณ

หากทั้ง 3 และ 0x33333333 ได้พูดบางอย่างเช่น NUM_WIDGET_SHIFT_BITS และ WIDGET_READ_MASK รหัสจะง่ายต่อการอ่าน

ความอัปยศในที่ใดก็ตามนำสิ่งนี้ออกในโครงการโอเพนซอร์ส แต่แม้กระทั่งสำหรับความคิดเห็นของรหัสส่วนตัวที่ดีและใช้การกำหนด / enums ที่มีความหมายและมีมาตรฐานการเข้ารหัสของคุณเอง


ฉันคิดว่าค่าคงที่เลขฐานสิบหกจะอนุญาตเช่นกัน 0xFF00คืออ่านได้มากขึ้น (ให้ฉัน) 0b1111111100000000กว่า ฉันไม่ต้องการนับเพื่อกำหนดจำนวนบิตที่ตั้งค่าไว้
Kevin Vermeer

1

โค้ดเฉพาะชิ้นนี้นำมาจากหนังสือแฮกเกอร์ดีไลท์รูปที่ 5.2 ออนไลน์ใน C (ฟังก์ชั่นป๊อป) ที่นี่ หมายเหตุผู้เขียนแนะนำให้ใช้เวอร์ชั่นที่อัพเดตแล้ว: http://www.hackersdelight.org/HDcode/newCode/pop_arrayHS.c.txt

หากคุณต้องการเรียนรู้การเพิ่มประสิทธิภาพประเภทต่างๆเหล่านี้ฉันขอแนะนำหนังสือเล่มนั้น มันสนุก แต่ถ้าคุณไม่ทำการเขียนโปรแกรมระดับบิตต่ำมากคุณอาจไม่เข้าใจมัน และส่วนใหญ่คอมไพเลอร์ของคุณจะสามารถทำการปรับให้เหมาะสมเหล่านี้ได้หลายอย่างสำหรับคุณ

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


1

คำอธิบายตามตัวอย่าง ข้อมูลเป็นลำดับของบิต ให้นับจำนวนบิตบนไบต์ 01001101 ที่มีการดำเนินการดังต่อไปนี้: 1. เราสามารถตรวจสอบค่าของบิตสุดท้าย 2. เราสามารถเปลี่ยนลำดับ

  1. 01001101 -> ไบต์สุดท้ายคือ 1, total = 1 กะ
  2. 10100110 -> ไบต์สุดท้ายคือ 0, ทั้งหมด = 1 กะ
  3. 01010011 -> ไบต์สุดท้ายคือ 1, total = 2 กะ
  4. 10101001 -> ไบต์สุดท้ายคือ 1, ผลรวม = 3 กะ
  5. 11010100 -> ไบต์สุดท้ายคือ 0, ทั้งหมด = 3 กะ
  6. 01101010 -> ไบต์สุดท้ายคือ 0, ทั้งหมด = 3 กะ
  7. 00110101 -> ไบต์สุดท้ายคือ 1, ทั้งหมด = 4 กะ
  8. 10011010 -> ไบต์สุดท้ายคือ 0, ทั้งหมด = 4 กะ

คำตอบของเรา: 4.

มันไม่ยากใช่ไหม? เรื่องใหญ่กับการดำเนินงานระดับบิตคือมีสิ่ง จำกัด ที่เราสามารถทำได้ เราไม่สามารถเข้าถึงได้โดยตรง แต่เราสามารถรู้ค่าของบิตสุดท้ายเปรียบเทียบกับ MASK 00000001 และเราสามารถทำให้ทุกบิตเป็นบิตสุดท้ายด้วยการปฏิบัติการแบบกะ แน่นอนอัลกอริทึมผลลัพธ์จะดูน่ากลัวสำหรับผู้ที่ไม่คุ้นเคย ไม่มีอะไรเกี่ยวข้องกับความฉลาด


0

ฉันจะไม่บอกว่าคุณต้องการมันเว้นแต่งานที่คุณทำเกี่ยวข้องกับ:

  • การประมวลผลเสียง
  • การประมวลผลวิดีโอ
  • กราฟิก
  • ระบบเครือข่าย (โดยเฉพาะที่ขนาดแพ็คเก็ตสำคัญ)
  • ข้อมูลจำนวนมหาศาล

การจัดเก็บสิทธิ์ในแฟล็กสไตล์ยูนิกซ์ก็เป็นอีกการใช้งานเช่นกันหากคุณมีรูปแบบการอนุญาตที่ซับซ้อนเป็นพิเศษสำหรับระบบของคุณหรือต้องการยัดเยียดทุกอย่างให้เป็นไบต์เดียวโดยมีค่าใช้จ่ายในการอ่านได้

นอกเหนือจากพื้นที่เหล่านั้นฉันจะนับว่าเป็นข้อดีอย่างยิ่งหากนักพัฒนา / นักพัฒนาอาวุโสสามารถแสดงให้เห็นถึงการเปลี่ยนแปลงเล็กน้อยและการใช้ | & และ ^ เนื่องจากมันแสดงให้เห็นถึงความสนใจในอาชีพที่คุณสามารถบอกได้ว่านำไปสู่รหัสที่เสถียรและเชื่อถือได้มากขึ้น

เท่าที่ไม่ 'ได้รับ' วิธีการตั้งแต่แรกเห็นดังกล่าวคุณต้องอธิบายสิ่งที่มันทำและพื้นหลังบางส่วน ฉันจะไม่บอกว่ามันเกี่ยวข้องกับความฉลาด แต่คุณคุ้นเคยกับการทำงานกับเลขฐานสิบหกในแต่ละวันและการตระหนักถึงปัญหาที่รูปแบบบางอย่างสามารถแก้ไขได้

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