การทำงานประเภทบิท ECMAScript

ตัวคำสั่งปฏิบัติที่ใช้ปฏิบัติการด้านล่างของเลข (หรือแสดงเลขด้วย 32 ตำแหน่ง) คือ:

จำเป็นเรียบเรียงเลข

ECMAScript มีสองประเภทของเลขเบซิก ซึ่งคือเลขเบซิกที่มีสัญญาณ (ที่ยอมรับตัวเลขบวกและลบ) และเลขเบซิกที่ไม่มีสัญญาณ (ที่ยอมรับตัวเลขบวกเท่านั้น) ใน ECMAScript ทุกตัวเลขด้านในตัวเลขจะเป็นเลขเบซิกที่มีสัญญาณ มันหมายความว่าอะไร?

เลขเบซิกที่มีสัญญาณใช้ 31 บิตเพื่อแสดงค่าตัวเลข และใช้บิตที่ 32 แสดงสัญญาณของตัวเลข 0 แสดงตัวเลขบวก และ 1 แสดงตัวเลขลบ ช่วงที่สามารถใช้ได้ของตัวเลขอยู่ที่ -2147483648 ถึง 2147483647

มีสองวิธีที่แยกต่างกันสำหรับเก็บเลขเบซิกที่มีสัญญาณ หนึ่งเพื่อเก็บตัวเลขบวก และหนึ่งเพื่อเก็บตัวเลขลบ ตัวเลขบวกจะเก็บในรูปแบบเบซิกที่แท้ ทุกบิตใน 31 บิตแรกนั้นแสดงสิ่งที่เป็นเอกฉันท์ของ 2 จากบิตที่ 1 (บิต 0) แสดงค่า 20ที่ 2 (บิต 1) แสดงค่า 21บิตที่ไม่ได้ใช้จะถูกใส่เป็น 0 หรือไม่จะนับเข้าไป อย่างเช่น รูปแบบที่แสดงในภาพด้านล่างนี้เป็นรูปแบบแสดงของเลข 18:

32 บิทเนียมที่แสดงเป็นตัวเลขเศษ

เลข 18 ในรูปแบบเบซิกที่ใช้เพียง 5 บิตแรก หรือเรียกว่าตำแหน่งที่มีค่าสำคัญของเลขนี้ โดยการเปลี่ยนเลขเป็นข้อความสตริงที่เป็นรูปแบบเบซิก จะเห็นตำแหน่งที่มีค่าสำคัญของเลขนี้:

var iNum = 18;
alert(iNum.toString(2));	//แสดง "10010"

นี่เป็นรหัสที่เพียงแค่แสดงค่า "10010" ไม่ใช่การแสดง 32 บิตของ 18 ที่สำคัญ สำหรับเลขที่ไม่ได้ใช้จะไม่มีความสำคัญ เพราะเราใช้เพียง 5 บิตแรกเท่านั้นเพื่อกำหนดค่าเลขเดียวกัน อย่างเช่น รูปแบบด้านล่างนี้:

ตัวเลข 18 ที่แสดงด้วยบิทเนียม 5 ตำแหน่ง

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

  1. ระบุการแสดงเบี้ยนสองของเลขไม่มีสัญญาณ (เช่น หาการแสดงเบี้ยนเสริมของ -18 จะต้องระบุการแสดงเบี้ยนของ 18 ก่อน)
  2. หาเบี้ยนตรงข้าว ก็คือต้องแทน 0 ด้วย 1 และแทน 1 ด้วย 0
  3. ทำการเพิ่ม 1 บนเบี้ยนตรงข้าว

เพื่อระบุการแสดงเบี้ยนสองของ -18 จะต้องได้รับการแสดงเบี้ยนสองของ 18 ดังนี้

0000 0000 0000 0000 0000 0000 0001 0010

ต่อมา ทำการคำนวณเบี้ยนตรงข้าม ดังนี้

1111 1111 1111 1111 1111 1111 1110 1101

สุดท้าย ทำการเพิ่ม 1 บนเบี้ยนตรงข้าม ดังนี้

1111 1111 1111 1111 1111 1111 1110 1101
                                      1
---------------------------------------
1111 1111 1111 1111 1111 1111 1110 1110

ดังนั้น การแสดงเบี้ยนสองของ -18 คือ 1111 1111 1111 1111 1111 1111 1110 1110 จำได้ว่า ในการจัดการเลขจำนวนที่มีสัญญาณ ผู้พัฒนาไม่สามารถเข้าถึงบิตที่ 31

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

var iNum = -18;
alert(iNum.toString(2));	//แสดง "-10010"

รหัสนี้จะแสดงข้อความ "-10010" ไม่ใช่รหัสเบี้ยนเสริมทรงสอง ซึ่งเป็นการหลีกเลี่ยงการเข้าถึงบิตที่ 31 ในทางง่ายๆ ECMAScript จะจัดการกับเลขด้วยวิธีที่เรียบง่ายที่ไม่ต้องให้ผู้พัฒนาเกี่ยวข้องกับการใช้งาน

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

การแปลงเลขจำนวนไม่มีสัญญาณเป็นตัวอักษรเลขมีเพียงแค่ตัวอักษรที่มีความหมาย

注意:ทั้งหมดเลขจำนวนเป็นที่สำหรับเก็บเป็นเลขจำนวนมาตรฐานที่มีสัญญาณ ยกเว้นเครื่องหมายการทำงานบิตของ ECMAScript ที่สามารถสร้างเลขจำนวนไม่มีสัญญาณได้

การทำงานบิต NOT

การทำงานบิต NOT นำ้วนด้วยเครื่องหมายหลังคำ ( ~ ) มันเป็นหนึ่งในเครื่องหมายการทำงานบิตที่เกี่ยวข้องกับการคำนวณทรงสองที่เหลือเล็กน้อยใน ECMAScript。

การทำการ NOT คือกระบวนการสามขั้นตอน

  1. การแปลงตัวเลขประกอบเลขเป็นเลข 32 บิต
  2. การแปลงเลขเบนารี่เป็นเลขเบนารี่ของมันเอง
  3. การแปลงเลขเบนารี่เป็นเลขจำนวนเป็นจำนวนทศนิยม

ตัวอย่าง:

var iNum1 = 25;		// 25 เท่ากับ 00000000000000000000000000011001
var iNum2 = ~iNum1;	// แปลงเป็น 11111111111111111111111111100110
alert(iNum2);		// ออก "-26"

การทำการ NOT ในต้นทางคือการหาลบของตัวเลข หลังจากนั้นลดลง 1 ดังนั้น 25 จะเป็น -26 สามารถทำได้ด้วยวิธีที่ต่อไปนี้ด้วย:

var iNum1 = 25;
var iNum2 = -iNum1 -1;
alert(iNum2);	// ออก -26

การทำการ AND

การทำการ AND ด้วยสัญลักษณ์ (+) ทำงานโดยตรงกับรูปแบบบีนารี่ของตัวเลข มันจะจัดลำดับตำแหน่งตัวเลขของแต่ละตัวเลข แล้วทำการ AND กับตำแหน่งเดียวกันของสองตำแหน่งตัวเลขตามกฎที่ต่อไปนี้:

ตำแหน่งของเลขที่เลขที่หนึ่ง ตำแหน่งของเลขที่เลขที่สอง ผลลัพธ์
1 1 1
1 0 0
0 1 0
0 0 0

ตัวอย่าง ให้ทำการ AND ระหว่างตัวเลข 25 และ 3 ตามต่อไปนี้:

var iResult = 25 & 3;
alert(iResult);	// ออก "1"

ผลการทำการ AND ระหว่าง 25 และ 3 คือ 1 ทำไม? นิยายดังนี้:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
AND = 0000 0000 0000 0000 0000 0000 0000 0001

สามารถเห็นได้ว่าใน 25 และ 3 มีเพียงตำแหน่งตัวเลขเดียว (ตำแหน่ง 0) ที่เก็บค่า 1 ดังนั้น ตำแหน่งที่เหลือจะมีค่า 0 ดังนั้นผลลัพธ์คือ 1

การทำการ OR

การทำการ OR ด้วยสัญลักษณ์ (|) และทำงานโดยตรงกับรูปแบบบีนารี่ของตัวเลข ในการคำนวณแต่ละตำแหน่ง การทำการ OR ใช้กฎที่ต่อไปนี้:

ตำแหน่งของเลขที่เลขที่หนึ่ง ตำแหน่งของเลขที่เลขที่สอง ผลลัพธ์
1 1 1
1 0 1
0 1 1
0 0 0

ยังคงใช้ตัวอย่างของการทำการ AND โดยใช้ตัวอย่าง 25 และ 3 ทำการ OR ตามต่อไปนี้:

var iResult = 25 | 3;
alert(iResult);	// ออก "27"

ผลการทำการ OR ระหว่าง 25 และ 3 คือ 27:

25 = 0000 0000 0000 0000 0000 0000 0001 1001
 3 = 0000 0000 0000 0000 0000 0000 0000 0011
--------------------------------------------
OR = 0000 0000 0000 0000 0000 0000 0001 1011

สามารถเห็นได้ว่า ในสองตัวเลข มี 4 ตำแหน่งตัวเลขที่เก็บค่า 1 ซึ่งถูกส่งผ่านไปยังผลลัพธ์ โค้ดบีนารี่ 11011 มีค่าเท่ากับ 27

การทำปฏิบัติทางบิท XOR

การทำปฏิบัติทางบิท XOR ที่แสดงด้วยสัญญาณ (^) ธรรมดาและทำงานโดยตรงเกี่ยวกับรูปแบบบิท. XOR ต่างจาก OR มันจะกลับมาเป็น 1 เมื่อมีเพียงตำแหน่งเดียวที่เก็บเลข 1. ตารางความเทียบดังนี้:

ตำแหน่งของเลขที่เลขที่หนึ่ง ตำแหน่งของเลขที่เลขที่สอง ผลลัพธ์
1 1 0
1 0 1
0 1 1
0 0 0

การทำ XOR ระหว่าง 25 และ 3 ดังนี้:

var iResult = 25 ^ 3;
alert(iResult);	// แสดง "26"

ผลลัพธ์การทำ XOR ระหว่าง 25 และ 3 คือ 26:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0001 1010

จึงเห็นได้ว่าในสองเลขที่มี 4 ตำแหน่งที่เก็บเลข 1 โดยตรงนี้ ตำแหน่งเหล่านั้นถูกส่งผ่านไปยังผลลัพธ์. บิท 11010 ค่าเทียบเท่ากับ 26.

การเลื่อนซ้าย

การเลื่อนซ้ายบริหารด้วยสัญญาณเมื่อเทียบกัน (<<). มันจะเลื่อนทุกตำแหน่งของเลขทั้งหมดไปทางซ้ายด้วยจำนวนที่กำหนด. ตัวอย่าง การเลื่อนเลข 2 (ที่เทียบเท่ากับ 10 บิท) 5 ตำแหน่งซ้ายจะได้ผลลัพธ์เป็น 64 (ที่เทียบเท่ากับ 1000000 บิท):

var iOld = 2;		// ค่าเทียบเท่ากับ 10 บิท
var iNew = iOld << 5;	// ค่าเทียบเท่ากับ 1000000 บิท หรือ 64 แบบเลขเทคโนโลยีเดียวกัน

注意:ในการเลื่อนตำแหน่งซ้าย จะมีช่องว่าง 5 ตำแหน่งที่ด้านขวาของเลข. การเลื่อนซ้ายจะใช้ 0 กระบวนการเติมช่องว่างเหล่านั้น ทำให้ผลลัพธ์เป็นเลข 32 บิตที่สมบูรณ์.

ตัวเลข 2 ทำการเลื่อนซ้าย

注意:การเลื่อนซ้ายบริหารเครื่องหมายของเลข. ตัวอย่าง ถ้าเลื่อน -2 5 ตำแหน่งซ้าย ผลลัพธ์จะเป็น -64 ไม่ใช่ 64. “เครื่องหมายยังคงจัดเก็บที่ตำแหน่งที่ 32 หรือไม่?” ใช่และนี้จะทำงานด้วย ECMAScript ภายหลัง นักพัฒนาไม่สามารถเข้าถึงตำแหน่งที่ 32 ได้โดยตรง. แม้ว่าจะมีการแสดงเลขตัวละครสีดำเมื่อแสดงรูปแบบบิททั้งหมดของเลขลบ แต่ที่แสดงขึ้นมาคือรูปแบบเครื่องหมายลบ (เช่น -2 จะแสดงว่า -10).

การเลื่อนขวาด้วยสัญญาณเครื่องหมาย

การเลื่อนขวาด้วยสัญญาณเครื่องหมายที่แสดงด้วยสัญญาณเมื่อเทียบกัน (>>). มันจะเลื่อนทุกตำแหน่งของเลข 32 บิตทั้งหมดไปทางขวา และกลางความหมายของเลข (บวกหรือลบ). การเลื่อนขวาด้วยสัญญาณเครื่องหมายเป็นตรงกันข้ามกับการเลื่อนซ้าย. ตัวอย่าง การเลื่อน 64 5 ตำแหน่งไปทางขวาจะกลายเป็น 2:

var iOld = 64;		//เท่ากับ 1000000 ในระบบบิททัศน์ 2
var iNew = iOld >> 5;	//เท่ากับ 10 ในระบบบิททัศน์ 2 หรือ 2 ในระบบเลขฐาน 10

เช่นเดียวกัน การเลื่อนตำแหน่งจะก่อให้เกิดช่องว่าง ครั้งนี้ ช่องว่างตั้งอยู่ที่ด้านซ้ายของตัวเลข แต่ตั้งอยู่หลังจากสัญญาณตำแหน่ง ECMAScript จะใช้ค่าสัญญาณตำแหน่งเพื่อใส่ที่ช่องว่างเหล่านั้น เพื่อที่จะสร้างตัวเลขที่สมบูรณ์ เช่นภาพด้านล่างนี้:

ตัวเลข 64 ทำการเลื่อนขวาเศษ

ประกายการเลื่อนขวาที่ไม่มีสัญญาณ

ประกายการเลื่อนขวาที่ไม่มีสัญญาณนำทางด้วยสัญญาณสามเหลี่ยมใหญ่สาม (>>>), มันจะเลื่อนทุกบิทของตัวเลข 32 บิททั้งหมด สำหรับตัวเลขบวก ผลลัพธ์ของประกายการเลื่อนขวาที่ไม่มีสัญญาณเหมือนกับประกายการเลื่อนขวาที่มีสัญญาณ

ในตัวอย่างของประกายการเลื่อนขวาที่มีสัญญาณ ถ้าเลื่อน 64 5 บิท จะกลายเป็น 2:

var iOld = 64;		//เท่ากับ 1000000 ในระบบบิททัศน์ 2
var iNew = iOld >>> 5;	//เท่ากับ 10 ในระบบบิททัศน์ 2 หรือ 2 ในระบบเลขฐาน 10

สำหรับตัวเลขลบ สถานการณ์นี้แตกต่าง

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

เนื่องจากผลลัพธ์ของประกายการเลื่อนขวาที่ไม่มีสัญญาณเป็นตัวเลขบวก 32 บิท ประกายการเลื่อนขวาที่ไม่มีสัญญาณของตัวเลขลบจะได้ตัวเลขใหญ่มาก ตัวอย่างเช่น ถ้าเลื่อน -64 5 บิท จะได้ 134217726 แล้วว่าจะได้ผลลัพธ์นี้ได้อย่างไร?

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

var iUnsigned64 = -64 >>> 0;

หลังจากนั้น ใช้ toString() ของ Number ที่แท้จริงของมันเพื่อใช้ตัวแทนของบิททัศน์ของมัน ใช้ฐาน 2:

alert(iUnsigned64.toString(2));

นี่จะสร้าง 11111111111111111111111111000000 ซึ่งเป็นการแสดงทางบิททัศน์ของเศษเต็มของเศษเต็ม -64 แต่มันเท่ากับเศษเต็ม 4294967232

ด้วยเหตุนี้ ใช้ประกายการเลื่อนขวาที่ไม่มีสัญญาณต้องระมัดระวัง