ตัวดำเนินการระดับบิต ในภาษา JavaScript
ในบทนี้ เป็นเนื้อหาของตัวดำเนินการระดับบิตในภาษา JavaScript คุณจะได้เรียนรู้ว่าตัวดำเนินการระดับบิตคืออะไร และมันถูกนำไปใช้อย่างไรในการเขียนโปรแกรม
ตัวดำเนินการระดับบิต
ตัวดำเนินการระดับบิต (Bitwise operators) คือตัวดำเนินการที่ดำเนินการในระบิตของข้อมูล โดยทั่วไปแล้วตัวดำเนินการระดับบิตมักใช้ในการเขียนโปรแกรมระดับต่ำ (Low level) เนื่องจากมันมีการทำงานที่เรียบง่ายและรวดเร็วในการคำนวณและเปรียบเทียบค่า เพราะการทำงานนั้นเกิดขึ้นกับแต่ละบิตในหน่วยความจำโดยตรง
ในบทนี้ เราจะใช้ตัวตัวดำเนินการระดับบิตกับตัวเลขจำนวนเต็มเพื่อความง่าย ในการเขียนคอมพิวเตอร์นั้น ข้อมูลจะถูกเก็บในหน่วยความจำในรูปแบบของเลขฐานสอง (Binary form) นี่เป็นตารางแสดงความสัมพันธ์ค่าของตัวเลขจาก 0 ถึง 15 กับค่าที่เก็บในหน่วยความจำ
DECIMAL BINARY DECIMAL BINARY
0 0000 8 1000
1 0001 9 1001
2 0010 10 1010
3 0011 11 1011
4 0100 12 1100
5 0101 13 1101
6 0110 14 1110
7 0111 15 1111
ในตัวอย่าง เป็นการแสดงค่าในรูปแบบเลขฐานสองของตัวเลข 0 ถึง 15 ในทางทฤษฎีแล้ว ภาษา JavaScript นั้นเก็บตัวเลขโดยใช้หน่วยความจำ 64 บิต นั่นหมายความว่า 5 ถูกเก็บในหน่วยความจำเป็น ...0101 โดยที่ ... หน้าตัวเลขนั้นประกอบไปด้วย 0 อีก 60 ตัว ในกรณีนี้เราแสดงเพียงบิตทางด้านขวาสุดเพื่อความเรียบง่าย
ต่อไปมาดูกันว่าตัวดำเนินการระดับบิตนั้นมีอะไรบ้าง และนี่เป็นตารางของตัวดำเนินการระดับบิตทั้งหมดในภาษา JavaScript
| สัญลักษณ์ | ตัวดำเนินการ | ตัวอย่าง |
|---|---|---|
| & | BIT AND | a & b |
| | | BIT OR | a | b |
| ^ | BIT XOR | a ^ b |
| ~ | BIT INVERT | ~a |
| << | BIT SHIFT LEFT | a << n |
| >> | BIT SHIFT RIGHT | a >> n |
ตัวดำเนินการระบิตนั้นทำงานคล้ายกับตัวดำเนินการตรรกศาสตร์ AND OR และ NOT แต่แทนที่จะจัดการกับค่า true และ false มันจะเป็นการทำงานกับแต่ละบิต 1 และ 0 ของข้อมูลแทน และนี่เป็นการทำงานของตัวดำเนินการแต่ละประเภท
- BIT AND: ได้ผลลัพธ์เป็น
1ถ้าค่าบิตทั้งสองเป็น1ไม่เช่นนั้นได้ผลลัพธ์เป็น0 - BIT OR: ได้ผลลัพธ์เป็น
1ถ้าค่าบิตอย่างน้อยหนึ่งบิตเป็น1ไม่เช่นนั้นได้ผลลัพธ์เป็น0 - BIT XOR: ได้ผลลัพธ์เป็น
1ถ้าค่าบิตทั้งสองแตกต่างกัน ไม่เช่นนั้นได้ผลลัพธ์เป็น0 - BIT INVERT: กลับบิตจาก
1เป็น0และกลับบิตจาก0เป็น1 - BIT SHIFT LEFT: เลื่อนบิตไปทางซ้าย
nตำแหน่ง และเติมบิต0เข้ามาทางขวาเป็นจำนวนnบิต - BIT SHIFT RIGHT: เลื่อนบิตไปทางขวา
nตำแหน่ง บิตทางขวาสุดnตำแหน่งจะถูกนำออกไป และเติมบิต0เข้ามาทางซ้าย
หลังจากที่ได้รู้ว่าตัวดำเนินแต่ละแบบนั้นทำงานอย่างไร ต่อไปมาดูตัวอย่างการใช้งาน เรามาเริ่มกับตัวดำเนินการ BIT AND และ BIT OR กันก่อน
console.log(3 & 10); // 2
console.log(3 | 10); // 11
ในตัวอย่าง เป็นการใช้งานตัวดำเนินการระดับบิตเพื่อจัดการกับค่าบิตของตัวเลขจำนวนเต็ม เนื่องจากในหน่วยความจำ (ที่แสดงในตารางก่อนหน้า) ค่าของ 3 และ 10 ถูกเก็บในรูปแบบของเลขฐานสองเป็น 0011 และ 1010 ตามลำดับ ดังนั้น การทำงานของตัวดำเนินการ BIT AND และ BIT OR สามารถแสดงให้เห็นเป็นรูปภาพได้ดังนี้
BIT AND
0011 (3)
1010 (10)
====
0010 (2)
ตัวดำเนินการจะทำงานทีละคู่ของบิตโดยเริ่มจากบิตทางด้านขวาสุดของ 3 และ 10 ไปยังบิตที่อยู่ทางด้านซ้าย
ในการทำงานของ BIT AND จะเห็นว่าทั้งบิตของ 3 และ 10 ในตำแหน่งที่สองจากทางด้านซ้ายมีค่าเป็น 1 ทั้งคู่ ดังนั้นบิตผลลัพธ์จึงมีค่าเป็น 1 และบิตในตำแหน่งอื่นๆ มีค่าผลลัพธ์เป็น 0 ดังนั้นผลลัพธ์ที่ได้จากการดำเนินการคือ 0010 ซึ่งมีค่าเท่ากับ 2 ในฐานสิบ
BIT OR
0011 (3)
1010 (10)
====
1011 (11)
ในการทำงานของ BIT OR ถ้าหากค่าบิตอย่างน้อยหนึ่งบิตเป็น 1 บิตผลลัพธ์จะมีค่าเป็น 1 นั่นทำให้มีเพียงบิตตำแหน่งที่สองจากทางซ้ายเท่านั้นที่ได้บิตผลลัพธ์เป็น 0 ส่วนตำแหน่งอื่นจะได้บิตผลลัพธ์เป็น 1 ดังนั้นผลลัพธ์ที่ได้จากการดำเนินการคือ 1011 ซึ่งมีค่าเท่ากับ 11 ในฐานสิบ
ตัวดำเนินการ BIT NOT นั้นทำงานกับค่าเพียงหนึ่งค่าเท่านั้น นี่เป็นตัวอย่าง
console.log(~7); // -8
เมื่อเราใช้งานตัวดำเนินการ BIT NOT มันได้ทำการกลับค่าบิตของเครื่องหมายด้วย ซึ่งตัวเลขในภาษา JavaScript นั้นมีบิตสำหรับเก็บว่าตัวเลขเป็นจำนวนบวกหรือลบ โดย 0 หมายถึงค่าบวก และ 1 หมายถึงค่าลบ
SIGN DIGIT
0 0111
============
1 1000
ดังนั้นตัวดำเนินการ BIT NOT ทำงานในสองส่วนคือกลับบิตที่เก็บค่าของตัวเลขจาก 0111 เป็น 1000 และกลับบิตเครื่องหมายจาก 0 เป็น 1 ดังนั้นผลลัพธ์ที่ได้จึงเท่ากับ -8 นั่นเอง
ตัวอย่างถัดมาเป็นการใช้ตัวดำเนินการ BIT SHIFT LEFT และ BIT SHIFT RIGHT สำหรับเลื่อนบิตไปทางซ้ายและทางขวาตามลำดับ นี่เป็นตัวอย่าง
console.log(8 >> 2); // 2
console.log(5 << 2); // 20
ในตัวอย่าง เราได้เลื่อนบิตไปทางซ้ายสองตำแหน่ง และเลื่อนไปทางขวาสองตำแหน่ง ซึ่งสามารถแสดงการทำงานแบบรูปภาพได้ดังนี้
BIT SHIFT RIGHT
1000
>>>> by 2
0010
ในการเลื่อนบิต 1000 ไปทางขวาสองตำแหน่ง จะทำให้บิตทางด้านขวาสุดสองบิตถูกนำออกไป และบิต 0 สองบิตเลื่อนเข้ามาแทนจากทางซ้าย ทำให้ได้บิตผลลัพธ์เป็น 0010 ซึ่งมีค่าเท่ากับ 2 ในฐานสิบ
BIT SHIFT LEFT
0101
<<<< by 2
10100
สำหรับการเลื่อนบิต 0101 ไปทางซ้ายสองตำแหน่ง จะทำให้มีบิต 0 เพิ่มเข้ามาจากทางด้านขวาสองตำแหน่ง นั้นทำให้ได้บิตผลลัพธ์เป็น 10100 ซึ่งมีค่าเท่ากับ 20 ในฐานสิบ
สังเกตว่าในการเลื่อนบิตไปทางขวาหนึ่งตำแหน่งจะทำให้ค่าลดลงครึ่งหนึ่ง และการเลื่อนบิตไปทางซ้ายหนึ่งตำแหน่งจะทำให้ค่าเพิ่มขึ้นสองเท่า
การแสดงตัวเลขในรูปแบบเลขฐานสอง
เมื่อคุณต้องการทำงานกับตัวเลขในรูปแบบเลขฐานสอง ยกตัวอย่างเช่น ต้องการทราบว่าตัวเลขแสดงในรูปแบบของฐานสองเป็นอย่างไร คุณสามารถให้เมธอด toString เพื่อแปลงตัวเลขให้เป็น String ในเลขฐานสองได้ โดยกำหนดพารามิเตอร์ที่สองเป็น 2 นี่เป็นตัวอย่าง
console.log((3).toString(2)); // 11
console.log((10).toString(2)); // 1010
console.log((0.5).toString(2)); // 0.5
console.log((2.8).toString(2)); // 10.110011...
และในทางกลับกัน ถ้าหากคุณมี String ของตัวเลขในรูปแบบเลขฐานสองและต้องการแปลงเป็นตัวเลขจำนวนเต็ม คุณสามารถใช้ฟังก์ชัน parseInt โดยใส่พารามิเตอร์ตัวที่สองเป็น 2 เพื่อแปลงจากเลขฐานสองเป็นจำนวนเต็มได้ นี่เป็นตัวอย่าง
let a = parseInt("11", 2);
let b = parseInt("1010", 2);
console.log(a); // 3
console.log(b); // 10
และนี่เป็นผลลัพธ์การทำงานของตัวอย่างการใช้ตัวดำเนินการระดับบิตของเรา โดยปกติแล้ว ฟังก์ชัน console.log จะแสดงข้อมูลเป็นเลขฐานสิบเสมอ และเพื่อดูมันในรูปแบบของเลขฐานสอง เราใช้เมธอด toString ในการแปลงก่อนการแสดงผล
console.log((3 & 10).toString(2)); // 10
console.log((3 | 10).toString(2)); // 1011
console.log((~7).toString(2)); // -1000
console.log((8 >> 2).toString(2)); // 10
console.log((5 << 2).toString(2)); // 10100
และนี่เป็นเพียงเทคนิคการใช้งานเมธอดเมื่อเราต้องทำงานกับตัวเลขและต้องการใช้มันในรูปแบบของเลขฐานสองเท่านั้น ในความเป็นจริงแล้วเมธอด toString และ parseInt สามารถทำงานกับตัวเลขฐานอื่นๆ ได้ เช่น ฐานแปด หรือฐานสิบหก เป็นต้น นี่เป็นรูปแบบการใช้งานของฟังก์ชันทั้งสอง
// Convert number to base n string
Number.toString(n);
// Parse string from base n to number (base 10)
Number.parseInt(str, n);
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับตัวดำเนินการระดับบิตในภาษา JavaScript ซึ่งเป็นตัวดำเนินการที่เราสามารถใช้มันจัดการกับบิตของข้อมูลได้โดยตรง นอกจากนี้ เรายังแนะนำเทคนิคการใช้งานเมธอด toString และ parseInt สำหรับแปลงตัวเลขไปและกลับระหว่างฐาน 10 และเลขฐานอื่นๆ