求解惑:为什么 18 位身份证的校验最后要除 11 而不是 10
转载
最近才需要做这个功能,才明白这个问题。18 位身份证的最后一位是校验位,取之前 17 位每一位乘以对应系数的和,得到个大整数,最后除以 11,得 0 - 10 这 11 个数,如果是 10,身份证上用 X 代替。
可能是我选的关键词有问题,以至于搜了好久也没能解开我的疑惑,为什么要除 11 而不是 10,如果除 10,身份证上将不再有 X,那会有更大的适用性。例如,在数据库里可以作为大整数而不是字符串存放,又比方说计算器那类很弱的液晶屏有些只能显示数字不能显示字母。我搜了半天只搜到很多人有跟我一样的疑问,却没有人能正经回答这个问题。
我搜到的回答,都是在解释“为什么会有 X”,这很好解答,“因为除以 11 后有可能余 10,所以用 X 代替 10”。但我的问题是“为什么要除以 11,而不是 10”,这是两个问题,所答非所问。
小张说设计身份证的人不至于这么简单的问题都绕不开,一定有更深层原因,比方说某些惯例、规范之类的。可在我看来除 10 的好处远大于 11 的。我也希望设计者不是 SB,但我实在想不出原因了,在表示谨慎的怀疑的同时求解
Update 感谢所有热心解答的朋友,希望得到更多的解答,[url=/blog/comments/364.html]你可以在这里留言[/url]
网友 卷心菜 给出的解释是这是 ISO 标准,我看了下这个 ISO 7064:1983, MOD 11-2,搜出的结果都是跟身份证有关的,我怀疑这是中国提交到 ISO 的标准,而非沿用 ISO 的已有标准,而且还没到最终原因上
网友 tangfl 的解释是因为 11 是质数,所以碰撞几率更小。还没怎么细想,感觉这种简单的 hash,在 MOD n 时碰撞几率就是 1/n,应该跟是不是质数没关系。也可能是我思维还没跟上去
另附身份证校验的 PHP 函数,如果像我一样之前没接触过的可以快速了解一下。
function checkIdentity($sIdentity) {
if (strlen($sIdentity) != 18) {
return FALSE;
}
$sVerify = "10X98765432";
$aWeight = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
foreach ($aWeight as $iOrder => $iWeight) {
$iVerify += $sIdentity[$iOrder] * $iWeight;
}
if ($sVerify[$iVerify % 11] != $sIdentity[17]) {
return FALSE;
}
// 还有些别的判定,户籍编号、日期合法性之类的,略
return TRUE;
}