舊制 15 碼:6碼地址 + 6碼出生年月日(YYMMDD) + 3碼順序碼(無西元年、無檢查碼)。
新制 18 碼:6碼地址 + 8碼出生年月日(YYYYMMDD) + 3碼順序碼 + 1碼檢查碼。
// 加權因子 (17 碼對應)
int[] weight = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
// 檢查碼對照 (索引 = 餘數 0~10)
string checkCodes = "10X98765432"; // 餘數 0→'1', 1→'0', 2→'X', ...
public static string Upgrade15To18(string id15)
{
if (string.IsNullOrWhiteSpace(id15) || id15.Length != 15)
throw new ArgumentException("輸入必須為 15 碼數字");
if (!id15.All(char.IsDigit))
throw new ArgumentException("15 碼身分證需全為數字");
// 1. 組合 17 碼本體
string body17 = id15.Substring(0, 6) + "19" + id15.Substring(6, 9);
// 2. 加權求和
int sum = 0;
for (int i = 0; i < 17; i++)
{
int digit = body17[i] - '0';
sum += digit * weight[i];
}
// 3. 取模對應檢查碼
int mod = sum % 11;
char checkChar = checkCodes[mod];
return body17 + checkChar;
}
// 使用範例
string id18 = Upgrade15To18("429005811009091"); // → 42900519811009091X
public static bool Validate18(string id18)
{
if (id18?.Length != 18) return false;
int sum = 0;
for (int i = 0; i < 17; i++)
sum += (id18[i] - '0') * weight[i];
int mod = sum % 11;
char expected = checkCodes[mod];
char actual = char.ToUpper(id18[17]);
return expected == actual;
}