หลักตรวจสอบและอัลกอริทึมที่ใช้สร้างมันขึ้นมานั้นมีอยู่หลายสาย แต่ถ้ามองข้ามรายละเอียดปลีกย่อยจะเห็นว่าแทบทุกสายใช้โครงเดียวกัน คือเอาเลขทุกหลักมายกน้ำหนัก บวกกัน แล้วหารเอาเศษกับค่ามอดุลัส ก่อนจะแปลงเศษที่ได้ให้กลายเป็นตัวอักษรหนึ่งตัวต่อท้ายหมายเลข คำถามที่นักพัฒนามักเจอคือต้องเลือกใช้สายไหนกับข้อมูลของตนเอง และทำไมบางสูตรจึงตรวจจับความผิดพลาดได้ดีกว่าอย่างเห็นได้ชัด บทความนี้จะเทียบให้เห็นภาพรวมของทั้งตระกูล
ตระกูลของอัลกอริทึมหลักตรวจสอบมีกี่สาย?
ถ้าแบ่งตามค่ามอดุลัสที่ใช้ จะแบ่งได้เป็นสามกลุ่มหลักที่ครอบคลุมการใช้งานส่วนใหญ่ในโลกของหมายเลข
- กลุ่มที่หารด้วยสิบ ซึ่งมักเรียกรวมกันว่า mod-10 และมีสมาชิกยอดนิยมอย่างสูตรที่คูณสลับหลักแล้วบวกผลคูณทั้งหมด กลุ่มนี้ทำงานง่าย เข้าใจเร็ว และเหมาะกับหมายเลขที่ใช้กันในชีวิตประจำวัน
- กลุ่มที่หารด้วยสิบเอ็ด ซึ่งเรียกสั้น ๆ ว่า mod-11 สมาชิกในกลุ่มนี้ต่างกันที่ตำแหน่งเริ่มของน้ำหนักและวิธีแมปเศษที่ได้กลับเป็นตัวอักษร
- กลุ่มที่หารด้วยเก้าสิบเจ็ด ซึ่งมักใช้กับหมายเลขที่ยาวและผสมทั้งตัวเลขกับตัวอักษร เพราะให้ผลลัพธ์ที่แยกแยะความผิดพลาดได้ละเอียดกว่า
นอกจากสามกลุ่มนี้ยังมีมาตรฐานสากลที่รวบรวมสูตรตรวจสอบไว้เป็นชุด ซึ่งเป็นที่รู้จักในชื่อ ISO 7064 และมีสมาชิกที่ใช้งานแพร่หลายหนึ่งตัวคือ MOD 97-10 ซึ่งถูกนำไปใช้กับการตรวจสอบ IBAN ตามที่อธิบายไว้ในบทความเรื่องโครงสร้าง IBAN และการตรวจสอบ mod-97
mod-10, mod-11 และ mod-97 ต่างกันตรงไหน
ความต่างที่สำคัญไม่ได้อยู่ที่ชื่อ แต่อยู่ที่ขนาดของเศษที่ได้และวิธีรับมือกับเศษนั้น ค่ามอดุลัสยิ่งมาก จำนวนเศษที่เป็นไปได้ก็ยิ่งมากตาม แต่เมื่อเศษมีค่ามากกว่าสิบ ก็จะไม่สามารถเขียนเป็นตัวเลขหนึ่งหลักได้อีกต่อไป จึงต้องมีข้อตกลงเพิ่มเติมว่าค่าที่เกินนั้นจะเขียนแทนอย่างไร
| กลุ่ม | ค่ามอดุลัส | ลักษณะเด่น | ข้อจำกัดที่ตามมา |
|---|---|---|---|
| mod-10 | หารด้วยสิบ | คำนวณเร็ว เข้าใจง่าย เหมาะกับหมายเลขสั้น | จับการสลับหลักได้เฉพาะกรณีที่สองหลักต่างกันเป็นค่าหนึ่ง |
| mod-11 | หารด้วยสิบเอ็ด | แยกแยะกรณีได้ละเอียดกว่า | เศษอาจเป็นสิบ ซึ่งต้องมีข้อตกลงว่าจะเขียนแทนอย่างไร |
| mod-97 | หารด้วยเก้าสิบเจ็ด | ใช้ได้กับหมายเลขยาวที่ผสมตัวอักษร | ต้องแปลงตัวอักษรเป็นตัวเลขก่อน จึงมีขั้นตอนมากกว่า |
ในกลุ่ม mod-11 เองก็มีหลายแบบย่อย ข้อตกลงเรื่องเศษที่เป็นสิบนั้นบางแห่งกำหนดให้ใช้ตัวอักษรเอกซ์แทน บางแห่งกำหนดให้ปรับค่าฐานก่อนคำนวณใหม่ นี่คือเหตุผลว่าทำไมคำว่า mod-11 เพียงคำเดียวจึงไม่พอจะบอกว่าหมายเลขหนึ่งผ่านหรือไม่ผ่าน เพราะยังต้องรู้ว่าระบบนั้นเลือกแบบย่อยใด
น้ำหนักและมอดุลัส: พารามิเตอร์ที่ปรับได้ในตระกูลเดียว
ถ้าลองเขียนโครงของตระกูลนี้ออกมาเป็นขั้นตอน จะได้สามขั้นที่แทบทุกสูตรใช้ร่วมกัน ขั้นแรกคือกำหนดน้ำหนักให้แต่ละตำแหน่ง ซึ่งอาจเป็นค่าคงที่ ค่าเพิ่มทีละหนึ่ง หรือค่าที่สลับกันไปมา ขั้นที่สองคือคูณและบวก ขั้นที่สามคือหารเอาเศษแล้วแปลงเศษเป็นตัวอักษร
ความต่างระหว่างสมาชิกในตระกูลจึงอยู่ที่การเลือกน้ำหนัก และอยู่ที่ว่าหลักตรวจสอบคำนวณจากเศษโดยตรงหรือจากค่าส่วนเติมเต็ม นั่นคือกรณีที่ระบบใช้ผลต่างระหว่างมอดุลัสกับเศษแทนตัวเศษเอง วิธีหลังช่วยให้เศษที่เป็นศูนย์ไม่ถูกเขียนออกมาซ้ำกับเศษอื่น
การทดลองกับตัวเลขสมมติสั้น ๆ จะช่วยให้เห็นภาพนี้ได้เร็ว แต่ควรใช้เฉพาะชุดที่เห็นชัดว่าเป็นค่าสาธิต เช่นชุดที่ขึ้นต้นด้วยศูนย์ล้วนหรือชุดที่ทุกหลักซ้ำกัน ซึ่งไม่มีทางเป็นหมายเลขที่ออกให้ใครจริง
ทำไมบางสูตรจึงจับการสลับหลักได้?
การสลับตำแหน่งของสองหลักที่อยู่ติดกันเป็นความผิดพลาดที่พบบ่อยมากในการคัดลอกด้วยมือ สูตรจะจับกรณีนี้ได้ก็ต่อเมื่อน้ำหนักของสองตำแหน่งนั้นไม่เท่ากันและค่าของสองหลักไม่สัมพันธ์กันแบบพิเศษ ถ้าน้ำหนักสมมาตร เช่นเพิ่มขึ้นแล้วลดลงเท่ากัน การสลับจะไม่เปลี่ยนผลรวมเลย และสูตรจะมองไม่เห็นความผิดพลาดนั้น
ด้วยเหตุนี้สูตรที่ใช้กับหมายเลขยาวจึงมักเลือกน้ำหนักที่ไม่สมมาตร และเลือกมอดุลัสที่มากพอจะแยกความต่างของเศษออกจากกันได้ ที่น่าสนใจคือการเพิ่มค่ามอดุลัสไม่ได้แก้ปัญหานี้ได้ทั้งหมด เพราะยังมีคู่ค่าบางคู่ที่ให้น้ำหนักต่างกันแล้วยังได้ผลรวมเท่าเดิมอยู่ดี
บทเรียนที่ใช้ได้จริงคืออย่าตั้งความหวังว่าสูตรใดจะจับความผิดพลาดได้ครบทุกแบบ การมีหลักตรวจสอบเป็นเพียงการกรองชั้นหนึ่งก่อนที่ข้อมูลจะไหลเข้าสู่ระบบ ซึ่งเป็นมุมเดียวกับที่อธิบายไว้ในหลักการของการตรวจสอบหมายเลข
สี่คำถามก่อนเลือกใช้สูตรหนึ่ง
ก่อนตัดสินใจว่าหมายเลขประเภทหนึ่งควรใช้สูตรใด ควรตอบคำถามสี่ข้อนี้ให้ครบเสียก่อน
- หมายเลขยาวเท่าใด และความยาวนั้นคงที่หรือเปลี่ยนแปลงได้ เพราะสูตรที่เหมาะกับหมายเลขสั้นยังใช้ได้ดี แต่เมื่อยาวขึ้นความเสี่ยงจากความผิดพลาดหลายตำแหน่งจะเพิ่มขึ้น
- ชุดอักขระเป็นตัวเลขล้วนหรือผสมตัวอักษร เพราะถ้ามีตัวอักษรปนอยู่ ต้องมีข้อตกลงการแปลงตัวอักษรเป็นตัวเลขที่ชัดเจนก่อนคำนวณ
- ความผิดพลาดส่วนใหญ่มาจากการพิมพ์ของคนหรือจากการสร้างด้วยเครื่อง เพราะสองแหล่งนี้ทิ้งร่องรอยต่างกัน และควรได้น้ำหนักที่ออกแบบมาคนละแบบ
- ถ้าเศษที่คำนวณได้มีค่ามากกว่าสิบ จะเขียนแทนด้วยอะไร และข้อตกลงนั้นเป็นที่ยอมรับของทุกฝ่ายที่ต้องอ่านหมายเลขนี้หรือไม่
คำถามข้อสุดท้ายมักถูกมองข้ามบ่อยที่สุด แต่เป็นข้อที่สร้างปัญหาจริงมากที่สุด เพราะข้อตกลงที่ไม่ตรงกันจะทำให้หมายเลขเดียวกันถูกตัดสินต่างกันโดยที่ทั้งสองฝ่ายคำนวณถูกต้องตามสูตรของตน
สำหรับนักพัฒนา: ตระกูลเดียวกันช่วยลดงานซ้ำอย่างไร
เมื่อรู้ว่าโครงของทุกสูตรเหมือนกัน การออกแบบส่วนตรวจสอบให้ใช้โครงกลางเพียงชุดเดียวก็เป็นไปได้ โดยให้ความต่างของแต่ละระบบถูกเก็บเป็นชุดพารามิเตอร์ ได้แก่ ตารางน้ำหนัก ค่ามอดุลัส ตำแหน่งเริ่มนับ และวิธีการแมปเศษกับตัวอักษร
ข้อดีของการทำเช่นนี้คือการเพิ่มระบบใหม่จะกลายเป็นการเพิ่มข้อมูลชุดหนึ่ง ไม่ใช่การเขียนตรรกะชุดใหม่ และชุดทดสอบชุดเดิมก็ยังใช้ตรวจสอบโครงกลางได้ต่อไป ข้อควรระวังคืออย่ารวบสูตรที่พฤติกรรมต่างกันจริงเข้าด้วยกันเพียงเพราะชื่อคล้ายกัน เพราะจะทำให้ระบบหนึ่งถูกตัดสินด้วยข้อตกลงของอีกระบบหนึ่ง
สิ่งที่ไม่ควรทำคือคิดสูตรขึ้นเองแล้วนำไปใช้กับหมายเลขของระบบที่มีข้อกำหนดอยู่แล้ว ให้ยึดตามคำอธิบายที่ระบบนั้นเผยแพร่ และตรวจสอบความถูกต้องของสูตรด้วยตัวอย่างอ้างอิงที่ระบบนั้นให้ไว้เสมอ ถ้าคุณต้องการทดลองกับชุดตัวเลขสมมติเพื่อดูว่าเศษที่ได้ตรงกับที่คาดไว้หรือไม่ เครื่องมือตรวจสอบจะแสดงผลลัพธ์และส่วนที่อธิบายได้ให้ทันที
ก้าวต่อไป
เริ่มจากการหยิบหมายเลขที่ระบบของคุณใช้จริงหนึ่งประเภท แล้วแยกให้ออกว่าองค์ประกอบใดเป็นชั้นของรูปแบบ และองค์ประกอบใดเป็นชั้นของหลักตรวจสอบ จากนั้นตรวจว่าคุณมีข้อตกลงเรื่องเศษที่มากกว่าสิบเขียนไว้ชัดเจนแล้วหรือยัง
ตัวเลขและค่าพารามิเตอร์ที่กล่าวถึงในบทความนี้เป็นความรู้สาธารณะ ส่วนตัวอย่างตัวเลขทั้งหมดถูกสมมติขึ้นเพื่อสาธิตสูตร ไม่ได้ออกโดยระบบใด และไม่ควรนำไปใช้แทนหมายเลขจริง