เลขคณิต กะ ขวา ไบนารี ตัวเลือก


เมื่อเลื่อนไปทางซ้ายไม่มีความแตกต่างระหว่างการคำนวณและการเปลี่ยนลอจิก เมื่อเปลี่ยนไปทางขวาประเภทของการเปลี่ยนจะขึ้นอยู่กับชนิดของค่าที่กำลังเปลี่ยน (เป็นพื้นหลังสำหรับผู้อ่านที่ไม่คุ้นเคยกับความแตกต่างการเปลี่ยนขวาตรรกะโดย 1 บิตจะเลื่อนบิตทั้งหมดไปทางขวาและกรอกข้อมูลในบิตด้านซ้ายสุดด้วย 0 การคำนวณการเปลี่ยนแปลงใบค่าเดิมในบิตซ้ายสุดความแตกต่างจะกลายเป็น สำคัญเมื่อจัดการกับตัวเลขลบ) เมื่อขยับค่าที่ไม่ได้ลงชื่อผู้ดำเนินการใน C คือการเปลี่ยนตรรกะ เมื่อเปลี่ยนค่าที่ลงนามผู้ดำเนินการจะเปลี่ยนเลขคณิต ตัวอย่างเช่นสมมติว่าเครื่องแบบ 32 บิต: ตอบเมื่อ 11 สิงหาคมที่เวลา 9:16 น. ใกล้ Greg คำอธิบายของคุณเกือบสมบูรณ์แบบ แต่การเปลี่ยนการแสดงออกของประเภทที่เซ็นชื่อและค่าลบคือการกำหนดใช้งาน ดู ISOIEC 9899: 1999 ส่วน 6.5.7 ndash Rob 22 กันยายนเวลา 22:53 น. ร็อบ: จริง ๆ แล้วสำหรับการเปลี่ยนแปลงทางด้านซ้ายและจำนวนที่ติดลบเชิงบวกพฤติกรรมนี้ก็ยังไม่ได้รับการยืนยัน ndash JeremyP เมษายน 4 12 at 15:24 ที่จริงการเปลี่ยนแปลงซ้ายยังส่งผลให้เกิดพฤติกรรมที่ไม่ได้กำหนดไว้สำหรับค่าที่ได้รับการเซ็นชื่อในเชิงบวกหากค่าทางคณิตศาสตร์ที่เกิดขึ้น (ซึ่งไม่สามารถระบุขนาดบิตได้) สามารถแสดงเป็นค่าบวกในประเภทที่มีการเซ็นชื่อ บรรทัดล่างคือคุณต้องเดินอย่างระมัดระวังเมื่อขวาขยับค่าลงนาม ndash Michael Burr Jun 21 13 at 0:30 ประการแรกคือความแตกต่างระหว่างการคำนวณทางตรรกะและคณิตศาสตร์จากมุมมองทางคณิตศาสตร์โดยไม่ต้องกังวลเกี่ยวกับขนาดของชนิดข้อมูล การเปลี่ยนลอจิกจะเติมบิตที่ถูกละทิ้งด้วยศูนย์ในขณะที่การคำนวณทางคณิตศาสตร์จะเติมเฉพาะศูนย์เท่านั้น แต่สำหรับการเปลี่ยนขวาจะทำสำเนา MSB ซึ่งจะรักษาเครื่องหมายของโอเปอเรเตอร์ไว้ (สมมติว่ามีการเข้ารหัสคู่สำหรับค่าลบ) กล่าวคือการเปลี่ยนลอจิคอลมองไปที่โอเปอเรเตอร์ที่เปลี่ยนไปเป็นเพียงเศษเสี้ยวของบิตและเคลื่อนย้ายโดยไม่ต้องกังวลเกี่ยวกับเครื่องหมายของค่าผลลัพธ์ การคำนวณการเปลี่ยนแปลงจะเป็นตัวเลข (ลงนาม) และเก็บรักษาเครื่องหมายไว้เมื่อมีการเปลี่ยนแปลง การเปลี่ยนเลขคณิตทางซ้ายของเลข X โดย n เทียบเท่ากับการคูณ X ด้วย 2 n และดังนั้นจึงเท่ากับตรรกะที่ยังเหลือ shift shift ตรรกะก็จะให้ผลเหมือนกันตั้งแต่ MSB อยู่แล้วตกออกสิ้นและ theres ไม่มีอะไรที่จะรักษา การคำนวณทางคณิตศาสตร์ที่ถูกต้องของจำนวนเต็ม x โดย n จะเท่ากับส่วนจำนวนเต็มของ X โดย 2 n เท่านั้นถ้า X เป็นค่าที่ไม่ใช่เชิงลบส่วนที่เป็นส่วนใดส่วนหนึ่งของคณิตศาสตร์และรอบไปทาง 0 (trunc) สำหรับตัวเลขลบแสดงโดย twos เสริมการเข้ารหัสขยับขวาโดย n บิตมีผลของการหารทางคณิตศาสตร์โดย 2 n และการปัดเศษไปทาง (พื้น) ดังนั้นการขยับขวาจะแตกต่างกันสำหรับค่าที่ไม่ใช่เชิงลบและค่าลบ สำหรับ X 0, X n X 2 n trunc (X 2 n) สำหรับ X lt 0, X n floor (X 2 n) ซึ่งเป็นการแบ่งทางคณิตศาสตร์คือการแบ่งจำนวนเต็ม ให้ดูตัวอย่าง: 37 2 18 (การปัดเศษ 18.5 ไปทาง 0) 10010) 2 ผลการแปลงเลขคณิตทางคณิตศาสตร์ -37) 10 11011011) 2 (พิจารณาส่วนประกอบ twos, แทน 8 บิต) -37 2 -18 (การปัดเศษ 18.5 ไปทาง 0) 11101110) 2 ไม่ใช่ผลลัพธ์ของการเปลี่ยนแปลงทางคณิตศาสตร์ --37 1 -19 (การปัดเศษ 18.5 ไปทาง) 11101101) 2 ผลการแปลงเลขคณิตตามที่ Guy Steele ชี้ ความคลาดเคลื่อนนี้ทำให้เกิดข้อบกพร่องในคอมไพเลอร์มากกว่าหนึ่งชุด ที่นี่ไม่ใช่เชิงลบ (คณิตศาสตร์) สามารถแมปไปยังค่าลบที่ไม่ได้ลงชื่อและลงนาม (C) ทั้งสองได้รับการปฏิบัติเดียวกันและขวาขยับพวกเขาจะทำโดยการหารจำนวนเต็ม ตรรกะและเลขคณิตมีค่าเท่ากันในการขยับซ้ายและค่าที่ไม่ใช่เชิงลบในการขยับขยายขยับขวาของค่าลบที่ต่างกัน ประเภทของโอเปอรแรนดและประเภทผลลัพ ธ มาตรฐาน C99 6.5.7: โอเปอรแรนดตองมีชนิดจํานวนเต็ม การโปรโมตจำนวนเต็มจะดำเนินการกับตัวถูกดำเนินการแต่ละตัว ชนิดของผลลัพธ์คือของโอเปอเรเตอร์ซ้ายที่เลื่อนขึ้น ถ้าค่าของโอเปอเรเตอร์ขวามีค่าเป็นลบหรือมากกว่าหรือเท่ากับความกว้างของโอเปอเรเตอร์ซ้ายที่ได้รับการเลื่อนแล้วพฤติกรรมจะไม่ได้กำหนดไว้ ในตัวอย่างข้างต้นโอเป็กทั้งสองจะกลายเป็น int (เนื่องจากมีการโปรโมตจำนวนเต็ม) ถ้า E2 เป็น negative หรือ E2 sizeof (int) CHARBIT การดำเนินการจะไม่ได้กำหนดไว้ เนื่องจากการขยับมากกว่าบิตที่มีอยู่แน่นอนจะล้น ถ้า R ถูกประกาศว่าสั้น ผลลัพธ์ int ของการดำเนินการเปลี่ยนจะถูกแปลงให้โดยนัยเพื่อเป็นการลดการแปลงที่แคบลงซึ่งอาจนำไปสู่พฤติกรรมการกำหนดใช้งานได้หากค่านี้ไม่สามารถแสดงได้ในประเภทปลายทาง ซ้าย Shift ผลลัพธ์ของ E1 ltlt E2 คือตำแหน่ง E2 ที่เลื่อนไปทางซ้ายของ E1 ตำแหน่งว่างบิตที่เต็มไปด้วยศูนย์ ถ้า E1 มีชนิด unsigned ค่าของผลลัพธ์คือ E12 E2 modulo ลดลงมากกว่าค่าสูงสุดที่แสดงได้ในประเภทผลลัพธ์ ถ้า E1 มีชนิดที่มีการลงนามและค่าที่ไม่ใช่ค่าลบและ E12 E2 สามารถแสดงได้ในประเภทผลการค้นหานั่นคือค่าที่เป็นผลลัพธ์มิฉะนั้นพฤติกรรมจะไม่ได้รับการกำหนด เนื่องจากการเปลี่ยนแปลงด้านซ้ายเหมือนกันสำหรับทั้งสองบิตที่ว่างเปล่าจะเต็มไปด้วยศูนย์เพียงอย่างเดียว จากนั้นจะระบุว่าทั้งสองประเภทที่ไม่ได้ลงชื่อและลงชื่อเป็นเลขคณิต Im ตีความว่าเป็นกะเลขคณิตตั้งแต่กะตรรกะ dont รำคาญเกี่ยวกับค่าที่แสดงโดยบิตก็แค่มองไปที่มันเป็นกระแสบิต แต่พูดมาตรฐานไม่ได้ในแง่ของบิต แต่โดยการกำหนดในแง่ของมูลค่าที่ได้รับโดย ผลิตภัณฑ์ของ E1 กับ 2 E2 ข้อแม้ที่นี่คือสำหรับประเภทที่ลงนามควรเป็นค่าที่ไม่ใช่ค่าลบและควรให้ผลลัพธ์ที่ได้ในประเภทผลลัพธ์ มิฉะนั้นการทำงานจะไม่ได้กำหนดไว้ ประเภทผลลัพธ์จะเป็นประเภทของ E1 หลังจากใช้โปรโมชั่นแบบครบวงจรไม่ใช่ปลายทาง (ตัวแปรที่จะเก็บผล) ไว้ ค่าผลลัพธ์จะถูกแปลงไปเป็นประเภทปลายทางโดยนัยถ้าไม่สามารถแสดงได้ในประเภทนั้นการแปลงเป็นข้อกำหนดการใช้งาน (C99 6.3.1.33) ถ้า E1 เป็นแบบที่มีการเซ็นชื่อมีค่าเป็นลบแล้วพฤติกรรมของการขยับซ้ายจะไม่ได้รับการกำหนด นี่เป็นเส้นทางที่ง่ายสำหรับพฤติกรรมที่ไม่ได้กำหนดซึ่งอาจมองข้ามได้ง่าย ขวา Shift ผลของ E1 E2 คือตำแหน่ง E2 ที่เลื่อนไปทางขวา E1 ถ้า E1 มีประเภทที่ไม่ได้รับการรับรองหรือถ้า E1 มีชนิดที่มีการเซ็นชื่อและค่าที่ไม่ใช่เชิงลบค่าของผลลัพธ์คือส่วนที่เป็นส่วนประกอบของส่วนของ E12 E2 ถ้า E1 มีชนิดที่มีการเซ็นชื่อและมีค่าเป็นลบค่าที่ได้จะถูกกำหนดใช้งาน การเปลี่ยนสิทธิสำหรับค่าที่ไม่เป็นลบและไม่ได้ลงชื่อซึ่งมีค่าไม่ถูกต้องค่อนข้างตรงไปตรงมาบิตที่ว่างจะเต็มไปด้วยศูนย์ สำหรับค่าลบที่เซ็นชื่อผลลัพธ์ของการขยับขวาคือการกำหนดใช้งาน ที่กล่าวว่าการใช้งานส่วนใหญ่เช่น GCC และ Visual C ใช้การขยับขวาเป็นเลขคณิตที่ขยับโดยการรักษาเครื่องหมายบิตไว้ ข้อสรุปแตกต่างจาก Java ซึ่งมีตัวดำเนินการพิเศษ gtgtgt สำหรับการเปลี่ยนลอจิกนอกเหนือจาก gtgt และ ltlt ตามปกติ C และ C มีการคำนวณทางคณิตศาสตร์เพียงบางส่วนที่ยังไม่ได้ระบุและใช้งานได้ เหตุผลที่ฉันคิดว่าพวกเขาเป็นเลขคณิตเป็นเพราะถ้อยคำมาตรฐานการดำเนินการทางคณิตศาสตร์มากกว่าการรักษา operand ขยับเป็นกระแสของบิตนี้อาจเป็นเหตุผลว่าทำไมมันออกจากพื้นที่เหล่านั้น unimplementation กำหนดแทนการกำหนดเพียงกรณีทั้งหมดเป็นกะตรรกะ ในแง่ของประเภทของการเปลี่ยนที่คุณได้รับสิ่งที่สำคัญคือประเภทของค่าที่คุณขยับ แหล่งที่มาของข้อบกพร่องแบบคลาสสิกคือเมื่อคุณเปลี่ยนอักษรให้พูดปิดหน้ากาก ตัวอย่างเช่นถ้าคุณต้องการลดจำนวนซ้ายสุดของจำนวนเต็มที่ไม่ได้ลงชื่อคุณอาจลองทำเป็นหน้ากากของคุณ: แต่น่าเสียดายที่นี่จะทำให้คุณเป็นปัญหาเพราะหน้ากากจะมีบิตทั้งหมดของชุดเนื่องจากค่าถูกเปลี่ยน (0) จะถูกเซ็นชื่อจึงจะมีการเปลี่ยนเลขคณิต แต่คุณต้องการบังคับการเปลี่ยนแปลงตามตรรกะด้วยการประกาศค่าอย่างชัดเจนว่าไม่ได้ลงนามโดยการทำสิ่งต่างๆเช่นนี้: ดีฉันมองขึ้นมาบนวิกิพีเดีย และพวกเขาได้กล่าวนี้: C แต่มีเพียงหนึ่งผู้ดำเนินการเปลี่ยนสิทธิ,. คอมไพเลอร์ C หลายตัวเลือกการเปลี่ยนขวาที่จะทำขึ้นอยู่กับชนิดของจำนวนเต็มที่มีการเปลี่ยนแปลงที่มักจะลงนามจำนวนเต็มจะถูกเปลี่ยนโดยใช้การเปลี่ยนแปลงเลขคณิตและ unsigned integers จะเปลี่ยนโดยใช้การเปลี่ยนตรรกะ ดูเหมือนว่ามันขึ้นอยู่กับคอมไพเลอร์ของคุณ นอกจากนี้ในบทความที่ทราบว่าการเปลี่ยนแปลงซ้ายเหมือนกันสำหรับเลขคณิตและตรรกะ ฉันอยากจะแนะนำการทำแบบทดสอบง่ายๆด้วยตัวเลขที่ลงนามและไม่ได้ลงนามในกรณีชายแดน (ชุดบิตสูงแน่นอน) และดูว่าผลที่ได้ในคอมไพเลอร์ของคุณ ฉันยังต้องการหลีกเลี่ยงการขึ้นอยู่กับมันเป็นหนึ่งหรืออื่น ๆ เนื่องจากดูเหมือนว่า C ไม่มีมาตรฐานอย่างน้อยหากมีเหตุผลและเป็นไปได้เพื่อหลีกเลี่ยงการพึ่งพาดังกล่าว ตอบเมื่อ Aug 11 08 at 9:18 แม้ว่าคอมไพเลอร์ C ส่วนใหญ่เคยมีค่า shift เลขคณิตสำหรับค่าเซ็นชื่อ แต่พฤติกรรมที่เป็นประโยชน์ดังกล่าวดูเหมือนจะถูกเลิกใช้ ปัจจุบันปรัชญาคอมไพเลอร์ดูเหมือนว่าจะถือว่าประสิทธิภาพของซ้ายกะในตัวแปรรับคอมไพเลอร์ที่จะสมมติว่าตัวแปรจะต้องไม่ใช่เชิงลบและจึงละเว้นรหัสใด ๆ ที่จะเป็นสิ่งที่จำเป็นสำหรับพฤติกรรมที่ถูกต้องถ้าตัวแปรเป็นลบ . ndash supercat Apr 16 15 at 5:47 left shift ltlt นี่เป็นวิธีที่ง่ายและเมื่อใดก็ตามที่คุณใช้โอเปอเรเตอร์ shift มันก็คือการดำเนินการบิตที่ชาญฉลาดดังนั้นเราจึงไม่สามารถใช้งานได้กับการทำงานแบบ double และ float เมื่อใดก็ตามที่เราเหลือการเปลี่ยนแปลงหนึ่งศูนย์จะมีการเพิ่มบิตน้อยที่สุด (LSB) เสมอ แต่ในการเปลี่ยนขวาเราต้องปฏิบัติตามกฎเพิ่มเติมหนึ่งข้อและกฎดังกล่าวเรียกว่าสำเนาบิตสัญลักษณ์ ความหมายของการทำเครื่องหมาย bit bit คือถ้าบิตที่สำคัญที่สุด (MSB) ถูกตั้งค่าและหลังจากการเปลี่ยนด้านขวาอีกครั้ง MSB จะถูกตั้งค่าหากมีการรีเซ็ตแล้วจึงรีเซ็ตอีกครั้งหมายถึงถ้าค่าก่อนหน้านี้เป็นศูนย์แล้วหลังจากที่ขยับอีกครั้ง bit เป็นศูนย์หากบิตก่อนหน้าเป็นหนึ่งแล้วหลังจากที่เปลี่ยนเป็นอีกครั้งหนึ่ง กฎนี้ใช้ไม่ได้กับการเปลี่ยนด้านซ้าย ตัวอย่างที่สำคัญที่สุดในการเปลี่ยนขวาถ้าคุณเปลี่ยนตัวเลขลบใด ๆ ไปยัง shift ขวาแล้วหลังจากที่บางขยับค่าในที่สุดถึงศูนย์แล้วหลังจากนี้ถ้าเปลี่ยน -1 จำนวนครั้งที่ค่าจะยังคงเหมือนเดิม โปรดตรวจสอบ. ตอบเมื่อวันที่ 30 มีนาคมเวลา 14.00 น. ตอนนี้กำลังอ่านหนังสือ Computer Systems มุมมองโปรแกรมเมอร์ ปัญหาหนึ่งในหนังสือกล่าวว่าเพื่อดำเนินการการเปลี่ยนแปลงทางตรรกะที่ถูกต้องเกี่ยวกับจำนวนเต็มที่ลงนามฉันลาดเทคิดวิธีการเริ่มต้นในเรื่องนี้ ต่อไปนี้เป็นคำถามที่เกิดขึ้นจริงจากหนังสือ กรอกรหัสสำหรับฟังก์ชัน C ต่อไปนี้ ฟังก์ชัน srl ดำเนินการการเปลี่ยนแปลงทางลอจิคัลโดยใช้การเปลี่ยนค่าทางคณิตศาสตร์ (ค่า xsra) ตามด้วยการดำเนินการอื่น ๆ ที่ไม่รวมการเปลี่ยนแปลงหรือการแบ่งสิทธิ ฟังก์ชั่น sra ทำการเปลี่ยนด้านเลขคณิตโดยใช้การเปลี่ยนทางลอจิคัล (ให้โดยค่า xsrl) ตามด้วยการดำเนินการอื่น ๆ ที่ไม่รวมการเปลี่ยนแปลงหรือการแบ่งสิทธิ คุณสามารถใช้การคำนวณ 8sizeof (int) เพื่อกำหนด w จำนวนบิตในชนิดข้อมูล int จำนวนกะของ k อาจมีค่าตั้งแต่ 0 ถึง 1 ฉันหวังว่าคุณจะเข้าใจคำถามนี้แล้ว ถามฉัน 27 กรกฎาคม 13 ที่ 3:18 ฉันไม่ให้คำตอบที่สมบูรณ์เช่นนี้ดูเหมือนว่าการบ้าน แต่ฉันจะให้คำแนะนำบางอย่างเพื่อช่วยให้คุณทำงานได้ด้วยตัวคุณเอง: สำหรับการเปลี่ยนขวาตรรกะของบิต N คุณต้องชัดเจนด้านบน N บิตของผลลัพธ์หลังจากเลขคณิตขยับคุณสามารถล้างบิตในค่าโดยการใช้หน้ากากที่เหมาะสม โดยปกติจะใช้บิตหรือ ANDOR หรือ XOR เพื่อลบค่า N bits ด้านบนของค่าที่คุณต้องการ mask ด้วย N 0s และบิตเหลือ 1 คุณสามารถสร้าง mask ที่เหมาะสมโดยใช้ shift ซ้ายโดยบิต W-N โดยที่ W คือจำนวนบิตใน คำ (ซึ่งคุณสามารถคำนวณเป็น W sizeof (int) CHARBIT) เช่น สำหรับการเปลี่ยนขวาตรรกะโดย 3 ส่วนที่ยากที่สุดคือการสร้างหน้ากาก แต่ถ้าคุณคิดว่าการเลื่อนซ้ายใช้เพื่อให้ค่าที่เหมาะสมอาจตามด้วยการดำเนินการบิตอย่างใดอย่างหนึ่งต่อไปคุณเร็ว ๆ นี้จะเห็นโซลูชันที่ค่อนข้างง่ายคือรูปแบบที่เกิดขึ้น การแสดงที่ถูกต้องสำหรับ -164 ไม่ใช่ผลลัพธ์แสดงจำนวนบวกจำนวนมากไม่ใช่ -4 Shift Right Arithmetic ตรรกะการเปลี่ยนสิทธิไม่สามารถใช้เพื่อแบ่งจำนวนเต็มลบเป็นสอง ปัญหาคือการเปลี่ยนสิทธิย้ายตรรกะศูนย์ไปที่บิตสั่งซื้อขั้นสูง นี่เป็นที่พึงประสงค์ในบางสถานการณ์ แต่ไม่ใช่สำหรับการหารจำนวนเต็มลบซึ่งบิตสั่งซื้อระดับสูงคือบิตเครื่องหมาย การเปลี่ยนแปลงด้านเลขคณิตจะทำซ้ำบิตการลงชื่อเข้าใช้ตามต้องการเพื่อเติมตำแหน่งบิต: คำถามที่ 13: จำเป็นต้องมีการเปลี่ยนเลขคณิตที่เหลืออยู่หรือไม่

Comments