[PHP] 身份證字號驗證 精簡版

by Mesak

工作需要要驗證身份證字號,不過網路上找到的版本沒辦法正確驗證

最後還是自己寫了一個 一般版精簡版

function pid_check($pid)
{   
    $iPidLen = strlen($pid);
    if(!preg_match("/^[A-Za-z][1-2][0-9]{8}$/",$pid) && $iPidLen != 10)
    {
        return FALSE;
    }
    $head = array("A"=>1,"B"=>0,"C"=>9,"D"=>8,"E"=>7,"F"=>6,"G"=>5,"H"=>4,"I"=>9,"J"=>3,"K"=>2,"M"=>1,"N"=>0,"O"=>8,"P"=>9,"Q"=>8,"T"=>5,"U"=>4,"V"=>3,"W"=>1,"X"=>3,"Z"=>0,"L"=>2,"R"=>7,"S"=>6,"Y"=>2);
    $pid  = strtoupper($pid);
    $iSum  = 0;
    for($i=0;$i<$iPidLen;$i++)
    {
        $sIndex = substr($pid,$i,1);
        $iSum   += (empty($i)) ? $head[$sIndex] : intval($sIndex) * abs( 9 - base_convert($i,10,9) );
    }
    return ( $iSum  % 10 == 0 ) ? TRUE:FALSE;
}

精簡版的意義就是 把 身份證字號的英文,直接轉換成 總數,接著 每個字元位置要分別乘以 1 9 8 7 6 5 4 3 2 1 1,省去了 1 & 9 就剩下 8 7 6 5 4 3 2 1 1

省去用陣列參照方式,把索引改為9進位模式, 遇到進位就變成 10 接著在 減掉 9 就是

9 - base_convert($i,10,9)

因為 9 – 10 所以 最後一個變成負的,在放個絕對值 函數 abs 就搞定…..

就可以這樣轉換

1 2 3 4 5 6 7 8 9
8 7 6 5 4 3 2 1 1

程式碼減少很多,不過會不會資源吃的更多呢 XD

另外也有其他種寫法,不用二進位

其實也可以不用用進位法表示

$point = (9-$i == 0) ? 9-$i : 1;

或是

$point = 9-$i;
if($point ==  0){$point++;}

最後一行改為

$iSum   += (empty($i)) ? $head[$sIndex] : intval($sIndex) * $point;

也是可以運作

另外謝謝 吳大雄 提示,英文參照表的部分,也可以直接省去十位數,只需要餘數就可以了

You may also like