เลขประจำตัวประชาชน 13 หลักของประเทศไทย ไม่ใช่แค่ตัวเลขที่เรียงกันแบบสุ่ม แต่มีโครงสร้างทางตรรกศาสตร์และความปลอดภัย (Checksum Verification) เพื่อป้องกันการกรอกข้อมูลผิดพลาด (Human Input Error) และการปลอมแปลงเบื้องต้น

บทความนี้จะพาคุณเจาะลึกโครงสร้างความหมายของแต่ละหลัก พร้อมแจกโค้ดคำนวณ Checksum ที่ผ่านการทดสอบแบบ Zero-dependency


1. โครงสร้างความหมาย 13 หลัก

เลข 13 หลักแบ่งออกเป็น 5 ส่วนสำคัญ:

[ X ] - [ X X X X ] - [ X X X X X ] - [ X X ] - [ X ]
  1         2              3            4         5
  1. หลักที่ 1 (ประเภทบุคคล):
    • เลข 1: คนไทยที่เกิดและแจ้งเกิดตามกำหนด (ตั้งแต่ 1 ม.ค. 2527)
    • เลข 2: คนไทยที่แจ้งเกิดเกินกำหนดเวลา
    • เลข 3: คนไทยและคนต่างด้าวที่มีชื่ออยู่ในทะเบียนบ้านก่อน 31 พ.ค. 2527
    • เลข 4: คนไทยและคนต่างด้าวที่ขอเพิ่มชื่อในทะเบียนบ้านภายหลัง
    • เลข 5: คนไทยที่ได้รับอนุมัติให้เพิ่มชื่อกรณีตกสำรวจ
    • เลข 6 ถึง 8: บุคคลต่างด้าวหรือผู้ไม่มีสัญชาติไทย
  2. หลักที่ 2-5 (รหัสสำนักทะเบียน): แสดงจังหวัดและอำเภอ/เขต ที่ออกสูติบัตรหรือขึ้นทะเบียน
  3. หลักที่ 6-10 (เล่มที่สูติบัตร): หมวดหมู่ตามเล่มเอกสาร
  4. หลักที่ 11-12 (ลำดับที่ในเล่ม): ลำดับบุคคลในเล่มนั้น
  5. หลักที่ 13 (Check Digit): ตัวเลขตรวจสอบความถูกต้อง คำนวณจาก 12 หลักแรกด้วย Modulo 11

2. อัลกอริทึม Modulo 11 Checksum

ขั้นตอนการคำนวณ Check Digit มีดังนี้:

  1. นำเลขแต่ละหลักตั้งแต่หลักที่ 1 ถึง 12 มาคูณกับน้ำหนัก (Weight) เริ่มต้นจาก 13 ถอยหลังลงไปถึง 2
  2. นำผลคูณทั้ง 12 หลักมารวมกัน (Sum)
  3. นำผลรวมที่ได้ไปหารเอาเศษด้วย 11 (Sum % 11)
  4. นำผลลัพธ์ไปลบออกจาก 11 (11 - (Sum % 11))
  5. นำหลักหน่วยของผลลัพธ์มาเป็น Check Digit (Result % 10)

สูตรทางคณิตศาสตร์

$$\text{Check Digit} = (11 - (\sum_{i=1}^{12} d_i \times (14 - i) \pmod{11})) \pmod{10}$$


3. ตัวอย่างการ Implementation ใน TypeScript

export function checkThaiNationalID(id: string): boolean {
  // ลบตัวอักษรขยะหรือขีดคั่นออก
  const cleanId = id.replace(/[^0-9]/g, '');

  if (cleanId.length !== 13) return false;
  if (cleanId.charAt(0) === '0') return false; // หลักแรกไม่เป็น 0

  let sum = 0;
  for (let i = 0; i < 12; i++) {
    sum += parseInt(cleanId.charAt(i), 10) * (13 - i);
  }

  const checkDigit = (11 - (sum % 11)) % 10;
  return checkDigit === parseInt(cleanId.charAt(12), 10);
}

4. ข้อควรระวังในการใช้งานจริง (Edge Cases)

[!WARNING] การตรวจสอบ Checksum ยืนยันได้เพียงว่า "ตัวเลขมีความสมบูรณ์ตามหลักคณิตศาสตร์" แต่ไม่ได้ยืนยันว่าบุคคลนั้นมีชีวิตอยู่จริง หรือมีตัวตนในฐานข้อมูลกรมการปกครอง หากต้องการตรวจสอบความถูกต้องของสถานะบุคคลจำเป็นต้องเชื่อมต่อ API กรมการปกครอง (DOPA Gateway)

  • การจัดเก็บข้อมูลส่วนบุคคล (PDPA): ควร Mask เลขบัตรประชาชน เช่น 1-1004-XXXXX-12-3 เมื่อแสดงผลบนหน้าเว็บ
  • หลีกเลี่ยง Regular Expression เพียงอย่างเดียว: การใช้ ^\d{13}$ ตรวจสอบได้แค่ความยาว แต่ไม่สามารถตรวจจับเลขที่มั่วขึ้นมาได้

ทดลองใช้งานเครื่องมือตรวจสอบเลขบัตรแบบ Interactive ได้ที่หน้า thutil Tools ของเราได้ทันที!