อารัมภบท ... นับแต่เด็กมา ผมเป็นคนค่อนข้างที่จะเรียนเก่ง พร้อมทั้งมีกิจกรรม คือ การเล่นดนตรี (ว่าง่ายๆไม่ใช่เด็กเรียนอย่างเดียวล่ะครับ) แน่นอนว่าปลายทาง คือ การเอ็นสะท้าน ... จวบจนมาถึงตอนเตรียมขึ้น ม.5 ผมถึงได้เปลี่ยนแปลงเส้นทางครั้งสำคัญในชีวิต ด้วยการ "ถอยหลัง" มา 1 ปี เพื่อย้ายมาเรียนสายอาชีพ ในสาขาอิเล็กทรอนิกส์ ... ผมไม่เคยนึกเสียใจเลยสักครั้ง ในการตัดสินใจย้ายมาเรียนสายช่างของผม ... เพราะความรู้ที่ร่ำเรียนมา มันได้ถูกนำมาใช้ทั้งในอดีต และ ปัจจุบัน ... แม้ว่าทัศนคติ และ ค่านิยมของผู้คนโดยส่วนใหญ่ มักจะมองว่าคนจบสายช่างมา ภูมิปัญญามันน้อย ไม่เก่งทฤษฎี เพราะอยู่ในสายปฏิบัติ ใช้กำลังแรงงานเป็นหลัก มากกว่าใช้สมอง แต่ ณ วันนี้ ผมแค่เศษเสี้ยวหนึ่งของคนที่จบช่างมา ก็ได้พิสูจน์ให้เห็น โดยที่แทบจะไม่ต้องมาบรรยายอะไรกันมากมายนัก ... บทความชุดนี้จึงขอนำเสนอแนวคิด ทักษะการปฏิบัติ เพื่อนำมาใช้งาน (ได้จริง) ... เนื่องจากสาขาอิเล็กทรอนิกส์ต้องเรียนวิชาแกนหลักอย่างเช่น วงจรดิจิตอล (จริง หรือ เท็จ/ตรรกศาสตร์) วิชาไมโครโปรเซสเซอร์ (เจาะลึกเข้าสู่การทำงานของคอมพิวเตอร์) ทั้ง 2 วิชานี้ ก็ล้วนแล้วแต่นำทางให้ผมสามารถเขียนโปรแกรมภาษา Assembly และ C ได้อย่างคล่องแคล่วในเวลาต่อมา ...
การแปลงเลขฐาน 10 เป็นเลขฐาน 16 (Visual Basic 6)
- Dim X as String
- X = Hex$(127)
จบแล้ว ... 55555+ ...
หากกรณีที่ตัวแปลภาษา มันไม่มีคำสั่ง (หรือฟังค์ชั่น) แล้วจะทำอย่างไรดีล่ะ ... ทำไม่ได้ครับ (ค่ะ) ... ก็กดเครื่องเลขเอาซิครับ ใน Windows มันมีมาให้ดูอยู่แล้ว (เฮ้อ ... โง่จังโว้ย คนถามเนี่ย) ... 55555+ ... ใครตอบมาแบบนี้ ก็อย่าอ่านบทความของผมต่อไปเลยน่ะครับ ... การแก้ปัญหาก็มีแนวคิดแบบการแปลงเลขฐาน 10 ไปเป็นเลขฐาน 2 ยังไงก็ยังงั้นเลยครับ ... พี่น้อง ... โดยคิดแบบการหารสั้น ... (คลิ๊กที่นี่ ... เพื่ออ่านรายละเอียด)
- ให้ฐาน 10 เป็นตัวตั้ง แล้วใช้เลขฐานที่ต้องการเป็นตัวหาร (เช่น 2 หรือ 16)
การหารมี 2 แบบ
- การหารเอาเศษ (MOD) ผลลัพธ์จะออกมาเป็นคำตอบ
- การหารตัดเศษ (Div) ไปเรื่อยๆ จนกว่าจะทำให้ผลลัพธ์สุดท้ายเป็น 0
เลขฐานสิบ
|
เลขฐานสอง
|
เลขฐานสิบหก
|
0
|
0000
|
0
|
1
|
0001
|
1
|
2
|
0010
|
2
|
3
|
0011
|
3
|
4
|
0100
|
4
|
5
|
0101
|
5
|
6
|
0110
|
6
|
7
|
0111
|
7
|
8
|
1000
|
8
|
9
|
1001
|
9
|
10
|
1010
|
A
|
11
|
1011
|
B
|
12
|
1100
|
C
|
13
|
1101
|
D
|
14
|
1110
|
E
|
15
|
1111
|
F
|
เนื่องจากตั้งแต่ค่า 10 - 15 (ฐาน 16) มันมีตัวเลข (Digit) ขนาด 2 หลัก จึงไม่เหมาะสมในการใช้งาน ... เขา (ผู้ที่คิด) จึงใช้ตัวอักขระ (Character) A - F แทนจำนวนดังกล่าวที่ว่ามาครับ ... พี่น้อง
เลขฐานมหัศจรรย์ ... เลขฐานใดๆจะมีค่าต่ำสุด = 0 และจะมีค่าสูงสุดเท่ากับฐานนั้นๆ - 1 เสมอ เช่น
- เลขฐาน 10 จะมีค่า 9 เป็นค่าสูงสุด (10 - 1 = 9)
- เลขฐาน 2 จะมีค่า 1 เป็นค่าสูงสุด (2 - 1 = 1)
- เลขฐาน 8 จะมีค่า 7 เป็นค่าสูงสุด (8 - 1 = 7)
- เลขฐาน 16 จะมีค่า 15 เป็นค่าสูงสุด (16 - 1 = 15)
เกี่ยวข้องอะไร ก็คิดๆเองกันบ้างเถอะน่ะครับ ... 55555+
ฟังค์ชั่น หรือ โปรแกรมย่อยในการแปลงเลขฐาน 10 เป็นฐาน 16 ด้วยวิธีการหารสั้น
' ==============================================================
Function Decimal2HexaDecimal(Dec As Long) As String
' ==============================================================
Dim Hex As String
' เงื่อนไขสุดท้าย ทำจนกว่า Dec = 0 ก็ให้จบกระบวนการ (True) ออกจากวงรอบ Do ... While
Do While (Dec > 0)
' Mod ด้วยอะไร ก็จะได้ค่าสูงสุด (ที่เป็นไปได้) ของตัว Mod ลบด้วย 1 เสมอ
' ดังนั้นเมื่อเอา 16 (ฐาน 10) มา Mod ทำให้ค่าสูงสุดที่ได้ (16 - 1) = 15 นั่นเอง
' เงื่อนไขในการดักค่าตั้งแต่ 10 แต่ไม่เกิน 15 เพราะ 10 แทนค่าด้วย A (ฐาน 16)
' 11 = B (ฐาน 16) และไปเรื่อยๆจน 15 = F (ฐาน 16)
Select Case (Dec Mod 16)
Case 10
Hex = "A" & Hex
Case 11
Hex = "B" & Hex
Case 12
Hex = "C" & Hex
Case 13
Hex = "D" & Hex
Case 14
Hex = "E" & Hex
Case 15
Hex = "F" & Hex
' ตั้งแต่ 0 - 9 มาประมวลผลที่ตรงนี้ครับ ... (รับรองการ Mod ด้วย 16 ยังไงๆ มันก็ไม่มีค่าเกิน 15 ไปได้หรอก)
' สังเกตด้วยครับ ทำไมผมเอาเงื่อนไขค่าระหว่าง 0 - 9 มาวางไว้ใน Case Else .. (มันไม่มีค่าอื่นอีกแล้วเหรอ).
Case Else
' เก็บค่าคำตอบของการหารเอาเศษ (MOD) ... เรียงลำดับให้ถูกต้องด้วยน่ะครับ
Hex = (Dec Mod 16) & Hex
End Select
' หารตัดเศษ (Div) จนกว่าจะได้ 0 ... เพื่อใช้เป็นเงื่อนไขในการวนรอบ Do ... While
Dec = Dec \ 16
Loop
' ส่งค่าคืนกลับในแบบ String เพราะเลขฐาน 16 มันมีตัวอักขระ A - F
Decimal2HexaDecimal = Hex
End Function
|
เห็นแนวคิดแบบบ้านๆหรือยังครับ ไม่ว่าคุณจะแปลงเลขฐาน 10 ไปเป็นเลขฐานใดๆ ก็จะใช้ Algorithm หลักๆเหมือนกันหมดเลย ... นี่แหละครับแบบฉบับช่าง (หัวมัน) ของผม ... เพราะผมไม่ได้อ้างอิงสูตร การยกกำลัง หรือใช้สมการใดๆเข้ามาเกี่ยวข้อง แต่แก้ปัญหาโจทย์ข้อนี้ได้ด้วยความรู้เรื่องการหารสั้น (ในระดับประถม) ทีนี้รู้หรือยังล่ะว่าเราเรียนพื้นฐานกันมาทำไม ... เรียนมาเพื่อประยุกต์ใช้ให้เป็นไงล่ะครับ ... ยังๆครับยังไม่หมด ยังมีอีก เอากันให้ชัดๆยิ่งกว่านี้ ว่าแนวคิดบ้านๆของช่างอิเล็กทรอนิกส์คนหนึ่ง จะแปลงเลขฐาน 2 ให้กลายเป็นเลขฐาน 16 ได้อย่างไร ...
 Design Time
 Run Time
จากตารางด้านบน ... ให้สังเกตน่ะครับว่า เลขฐาน 16 นั้น เราสามารถแทนที่มันด้วยเลข Binary (ฐาน 2) จำนวนขนาด 4 บิต
ว่ากันง่ายๆ เลข Binary จำนวนขนาด 4 บิต สามารถแทนเลขฐาน 16 ได้ครบพอดีเลย ...
- 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 ... นิพจน์อันนี้เห็นทีต้องไปหาขุดคุ้ยกันเอาเองน่ะครับ เพราะผมจะกล่าวถึงการนำเลข Binary 4 บิต มาแปลงเป็นฐาน 16
- 0 0 0 0 = 0
- 0 0 0 1 = 1
- 0 0 1 0 = 2
- 0 1 0 0 = 4
- ไปเรื่อย ...
- 1 1 1 0 = E (หรือ 14 ฐาน 10)
- 1 1 1 1 = F (หรือ 15 ฐาน 10)
เมื่อคิดได้ดังนี้แล้ว ... ผมจะจัดกลุ่มเลข Binary (ฐาน 2) ออกเป็นชุดๆละ 4 บิต โดยให้ นับจากขวาไปซ้าย (วงรอบ For) ... แต่วิธีการ อ่านค่าตำแหน่งของบิตซ้ายมือสุด ของทุกๆชุด ผมจะใช้การ อ่านค่าตำแหน่งจากซ้ายไปขวาแทน (เงื่อนไข IF เป็นเท็จ หรือ Else นั่นแหละ)
เช่น เลข 257 (ฐาน 10) จะกระจายเลข Binary ได้คือ 1 0 0 0 0 0 0 0 1
- 1 0 0 0 0 0 0 0 1 ... การแบ่งชุดเลข Binary ชุดละ 4 บิต
- 1 2 3 4 5 6 7 8 9 ... เวลาคำนวณหาตำแหน่งของบิตซ้ายมือสุด ในแต่ละชุด ผมจะพิจารณาหลัก 6 และ หลัก 2 (การอ่านตำแหน่งจากซ้ายไปขวา)
ลองดูจากโค้ดด้านล่างประกอบ และใช้ค่า 257 (ฐาน 10) เป็นค่าทดสอบ
- รอบที่ 1 คำสั่ง For Count = Len(BinaryBase) To 1 Step -4 ... ทำให้ Count มีค่าเท่ากับ 9 (ความยาวของจำนวนบิต หรือ Len(BinaryBase))
- ทำให้ Bit = Mid$(BinaryBase, Count - 3, 4) หรือ Mid$("100000001", 9 - 3 = 6, 4) = 0001 (บิต 0 สีแดง คือตำแหน่งที่นับจากทางซ้ายมือมา 6 ตำแหน่ง ... จากนั้นให้นับต่อไปทางขวาอีก 4 บิต
- รอบที่ 2 คำสั่ง For Count = Len(BinaryBase) To 1 Step -4 ... ทำให้ Count ลดค่าลง 4 (Step -4) จึงมีค่าเท่ากับ 9 - 4 = 5
- ทำให้ Bit = Mid$(BinaryBase, Count - 3, 4) หรือ Mid$("100000000", 5 - 3 = 2, 4) = 0000 (บิต 0 สีแดง คือตำแหน่งที่นับจากทางซ้ายมือมา 2 ตำแหน่ง ... จากนั้นให้นับต่อไปทางขวาอีก 4 บิต
- 1 ... กรณีของชุดสุดท้าย หากมีบิตไม่ครบ 4 บิต ... ใช้วิธีการเพิ่มบิต 0 เข้าไปให้ครบ (เงื่อนไข IF เป็นจริง)
เช่น ...
- ปรับขนาดบิตให้ครบ 4 บิต โดยเอาบิตมาเรียงกัน แล้วนับมาจากทางขวาคืนกลับมา 4 ตัว ...
- "0000" & "1" ... ปกติก็ได้การเรียงบิต ดังนี้ "00001"
- พอใช้ Right("0000" & "1", 4) ... เพื่อให้นับจากทางขวาไป 4 หลัก ... คำตอบ คือ "0001"
สิ่งต่างๆที่ได้เห็นทางด้านบน คือ การคิดออกแบบเอาไว้ แล้วลองทดสอบค่าลงในกระดาษ ผสมผสานกับการเขียนผังงานออกมาดู ... หากไม่ทำอย่างนี้ ก็ยากที่จะเขียนโปรแกรมออกมาเพื่อให้มีผลลัพธ์ที่ถูกต้องได้ ... ขอย้ำอีกครั้งสำหรับผู้ที่คิดจะเอาดีทางด้านนี้ ... การแปลงเลขฐาน 2 ไปเป็นเลขฐาน 16 ... ด้วยวิธีการนับจำนวนบิต ครั้งละ 4 บิต
' ==============================================================
' แปลงเลขฐาน 2 เป็นเลขฐาน 16 ... โดยทำการคิดเลขฐาน 2 คราวละ 4 บิต
Function Binary2HexaDecimal(BinaryBase As String) As String
' ==============================================================
Dim Count As Integer ' นับจำนวนบิตคราวละ 4 บิต
Dim Bit As String ' นำไปแปลงเป็นเลขฐาน 16
Dim Hex As String ' เก็บค่าที่แปลงเป็นเลขฐาน 16 เพื่อนำมาเวียนใช้งาน
' เลือกมาเป็นชุดๆละ 4 บิต ต้องนับจากทางขวามือมาน่ะครับ (LSB)
' ในฐาน 10 ก็เหมือนไล่จากหลักพัน หลักร้อย หลักสิบ หลักหน่วย (ตามปกติชีวิตที่คุ้นเคยกับตัวเลข)
' Count จะลดค่าลงทีละ 4 ครับ ... นับจำนวนความยาวของจำนวนบิต แล้วลดค่าลงทีละ 4 บิต
For Count = Len(BinaryBase) To 1 Step -4
' กรณีบืตทางซ้ายมือมันมีขนาดไม่ครบ 4 บิต ... อาศัยการเติม 0 เข้าไปซืครับ
' เช่น 1 0000 0001 ...
' การวนรอบครั้งสุดท้าย จะทำให้ค่า 1 ซึ่งเป็นบิตที่อยู่ซ้ายมือสุด (MSB) เหลือตัวเดียวโดดๆ
' ในกรณีที่ไม่ได้ค่าจำนวนบิตเป็น 4, 8, 12, 16, 20, ... ไปเรื่อยๆ (การหารด้วย 4 ลงตัวพอดี)
If Count < 4 Then
' ===========================================================
' ปรับขนาดบิตให้ครบ 4 บิต โดยเอาบิตมาเรียงกัน แล้วนับมาจากทางขวาคืนกลับมา 4 ตัว ...
' "0000" & "1" ... ปกติก็ได้การเรียงบิต ดังนี้ "00001"
' พอใช้ Right("0000" & "1", 4) ... คำตอบ คือ "0001"
Bit = Right$("0000" & Mid$(BinaryBase, 1, Count), 4)
' ===========================================================
Else
' ===========================================================
' ค่อยๆไล่หาวิธีการคิดน่ะครับ ...
' สมมุติหาค่า 257 (ฐาน 10) หรือ 1 0 0 0 0 0 0 0 1 (ฐาน 2)
' ทำให้ได้ความยาวทั้งหมด 9 บิต (Count = 9) ... ให้ลบออกด้วย 3 เพราะ ...
' 1 2 3 4 5 6 7 8 9 (นับหลัก)
' 1 0 0 0 0 0 0 0 1
' -----------x------- ... ผมต้องการตัดบิตขวามือ 3 บิตออก จึงทำให้ลบแล้วได้ตำแหน่ง x พอดี
' ดังนั้นรอบแรกเริ่ม 9 - 3 = 6 ... ให้ลองนับดูครับว่าจะเริ่มอ่านจากหลักที่ 6 พอดี นับจากซ้ายมือน่ะครับ
' จุดนี้สำคัญมากครับ ... ขอให้ไล่การทำงานด้วยการกด F8 ทดสอบดู
' เมื่อใช้ Mid$(ข้อความ, เริ่มต้นจากหลักที่, นับไป 4 ตัว) ...
' มันจะมีจำนวนบิตเข้ามาเท่าไร ก็ไม่มีปัญหากับแนวคิดของอดีตช่าง (หัวมัน) แบบผม ...
Bit = Mid$(BinaryBase, Count - 3, 4)
' ===========================================================
End If
' ได้มาครบ 4 บิตแล้วก็ทำการเปรียบเทียบค่า
Select Case Bit
Case "0000"
Hex = "0"
Case "0001"
Hex = "1"
Case "0010"
Hex = "2"
Case "0011"
Hex = "3"
Case "0100"
Hex = "4"
Case "0101"
Hex = "5"
Case "0110"
Hex = "6"
Case "0111"
Hex = "7"
Case "1000"
Hex = "8"
Case "1001"
Hex = "9"
Case "1010"
Hex = "A"
Case "1011"
Hex = "B"
Case "1100"
Hex = "C"
Case "1101"
Hex = "D"
Case "1110"
Hex = "E"
Case "1111"
Hex = "F"
End Select
' จัดเรียงการแสดงผล และ ส่งค่าคืนกลับไป (แบบ String)
Binary2HexaDecimal = Hex & Binary2HexaDecimal
Next
End Function
วิธีการ Debug Program
|
Conclusion: ผมยอมรับ ... โค้ดมันดูยาก ... โดยเฉพาะเงื่อนไข Bit = Mid$(BinaryBase, Count - 3, 4) ... ก็เพราะผมไม่ได้เขียน Flow Chart ออกมาให้ดู ซึ่งพี่น้องต้องฝึกคิดพิจารณาตามไปด้วยครับ มันมีวิธีการเขียนโค้ดออกมาได้หลายแบบ หลักๆก็หนีไปพ้นตัวอย่าง (ของจริง) ที่ทำไว้ให้ดูหรอกครับ เพียงแต่ผมรวบรัดคำสั่งให้ได้สาระสำคัญ โจทย์ประเภทนี้ผมมีเอาไว้สอนพวกระดับฝึกหัด (สอนในหลักสูตรแบบพื้นๆ เฉพาะแปลงเลขฐานไปมาเนี่ย เล่นกันเป็นเทอมยังได้เลย) ... ลองซิหากคุณไม่ออกแบบลงบนกระดาษมาซ่ะก่อน ก็ยากที่จะเขียนโค้ดออกมาได้ครับ ... ที่แน่ๆผมใช้แนวคิด และ เขียนขึ้นมาจากภาษา C มาก่อน นับได้ 10 กว่าปีแล้ว ก็ทำงานได้เช่นเดียวกัน เพราะ Algorithm นี้แทบไม่ได้เกี่ยวกับภาษาโปรแกรมที่ใช้เลยครับ ... พี่น้อง ... ประเด็นที่อยากชี้ให้เห็นอีกอย่างเลยว่า ผมไม่ได้นำหลักการคิดทางตัวเลขมาเกี่ยวข้องเลย ... อาศัยการใช้งานจริงล้วนๆครับ ... พี่น้อง
|