谁能用mathematica写个校验身份证的子函数?
(*身份证检验码*)Clear["Global`*"];(*Clear all variables*)
(*没考虑身份证号码最后一位x的情况*)
fun:=Module[{ids,dot},
jym={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
ids=IntegerDigits;
dot=Dot],jym];(*前17位与校验码求内积*)
dot=Mod;(*求余数*)
dot=Mod;(*余数n,对应的最后一位编码是12-x*)
If],Return,Return]
]
我写的这个未能考虑最后一位是X的情况,
最后一位是X,应该如何考虑呢? 这个容易,嵌套个特例啊 markfang2050 发表于 2019-4-19 15:13
这个容易,嵌套个特例啊
我自己用perl搞定了 mathematica 发表于 2019-4-26 11:39
我自己用perl搞定了
代码贴出啊,。C就可以。 (*
函数名称:IDCardValidate
函数功能:对输入的18位身份证号码进行合法性校验
输入参数:
id_String:表示输入的身份证号码,为字符串类型
返回值:
如果身份证号码合法,返回True;否则返回False
*)
IDCardValidate :=
Module[
{
idList, (* 用于存储身份证号码前17位转换后的数字列表 *)
weights, (* 身份证号码校验的加权因子列表 *)
sum, (* 用于存储前17位数字与加权因子乘积的总和 *)
checkDigits,(* 对应不同余数的正确校验码列表 *)
remainder,(* 总和对11取模后的余数 *)
expectedCheckDigit, (* 计算得出的预期校验码 *)
inputCheckDigit (* 输入身份证号码的最后一位校验码 *)
},
(* 检查输入的身份证号码长度是否为18位,如果不是,直接返回False *)
If != 18, Return];
(* 将身份证号码的前17位转换为数字列表 *)
idList = IntegerDigits]];
(* 定义身份证号码校验的加权因子列表 *)
weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
(* 计算前17位数字与加权因子乘积的总和 *)
sum = Total];
(* 计算总和对11取模后的余数 *)
remainder = Mod;
(* 定义对应不同余数的正确校验码列表 *)
checkDigits = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
(* 根据余数获取预期的校验码 *)
expectedCheckDigit = checkDigits[];
(* 获取输入身份证号码的最后一位校验码 *)
inputCheckDigit = StringTake;
(* 如果输入的校验码是"X"或"x",统一转换为"X" *)
If,
inputCheckDigit = "X"
];
(* 比较预期校验码和输入校验码是否一致,一致则返回True,否则返回False *)
expectedCheckDigit == inputCheckDigit
]
这是人工智能写的代码
看起来很不错
可读性非常强,还有详细注释与详细说明
nyy 发表于 2025-2-28 18:58
这是人工智能写的代码
看起来很不错
可读性非常强,还有详细注释与详细说明
" 函数功能:此函数用于校验一个18位的身份证号码是否合法。
" 依据中华人民共和国国家标准GB 11643-1999中规定的身份证号码编码规则进行校验。
" 输入参数:
" a:idcard - 字符串类型,代表需要校验的身份证号码,必须为18位。
" 返回参数:
" 1 - 如果身份证号码合法,符合编码规则。
" 0 - 如果身份证号码不合法,例如长度不为18位、字符不符合要求、校验码不正确等情况。
function! ValidateIDCard(idcard) abort
" 检查身份证号码的长度是否为18位,如果不是则直接返回0,表示不合法
if len(a:idcard) != 18
return 0
endif
" 定义加权因子数组,用于计算身份证号码前17位的加权和
let factor =
" 定义校验码数组,对应加权和取模11后的正确校验码
let parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
" 初始化加权和为0
let sum = 0
" 遍历身份证号码的前17位
for i in range(0, 16)
" 获取身份证号码当前位置的字符
let cur_char = a:idcard
" 将当前字符转换为数字(如果不是数字则返回-1)
let digit = str2nr(cur_char)
" 如果转换失败(不是数字字符),则返回0,表示不合法
if digit == -1
return 0
endif
" 将当前数字乘以对应的加权因子,并累加到加权和中
let sum += digit * factor
endfor
" 计算加权和对11取模的结果
let remainder = sum % 11
" 获取身份证号码的最后一位作为输入的校验码
let check_bit = a:idcard
" 将输入的校验码转换为大写(如果是X的情况),以便和parity数组比较
if check_bit =~# 'x'
let check_bit = 'X'
endif
" 比较输入的校验码和计算得到的正确校验码是否一致
if check_bit == parity
return 1
else
return 0
endif
endfunction
nyy 发表于 2025-2-28 21:13
" 测试用例 1:合法的身份证号码,最后一位是数字
let test_idcard1 = "110105194912310021"
let result1 = ValidateIDCard(test_idcard1)
echo "测试用例 1(合法,数字结尾):" . (result1 == 1? "通过" : "未通过")
" 测试用例 2:合法的身份证号码,最后一位是 X
let test_idcard2 = "11010519491231002X"
let result2 = ValidateIDCard(test_idcard2)
echo "测试用例 2(合法,X 结尾):" . (result2 == 1? "通过" : "未通过")
" 测试用例 3:不合法的身份证号码,长度不足 18 位
let test_idcard3 = "11010519491231002"
let result3 = ValidateIDCard(test_idcard3)
echo "测试用例 3(不合法,长度不足):" . (result3 == 0? "通过" : "未通过")
" 测试用例 4:不合法的身份证号码,包含非数字非 X 字符
let test_idcard4 = "11010519491231002A"
let result4 = ValidateIDCard(test_idcard4)
echo "测试用例 4(不合法,含非法字符):" . (result4 == 0? "通过" : "未通过")
" 测试用例 5:不合法的身份证号码,校验码不正确
let test_idcard5 = "110105194912310020"
let result5 = ValidateIDCard(test_idcard5)
echo "测试用例 5(不合法,校验码错误):" . (result5 == 0? "通过" : "未通过") nyy 发表于 2025-2-28 21:13
(*
函数功能:
该函数用于全面检验中国身份证号码的有效性,包括校验码是否正确、出生年份是否在合理范围内(1900至2100年)、
月份和日期是否符合实际情况。中国身份证号码由17位数字本体码和1位校验码组成。
校验码的计算方法是:将前17位数字分别乘以对应的加权因子(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2),
然后将乘积相加,再对结果取模11,根据模值得到对应的校验码字符(模值为0对应X,模值为1对应1,以此类推),
最后与输入的身份证号码的最后一位进行比较,判断校验码是否正确。
函数用法:
IsValidIDCard,传入一个字符串类型的身份证号码,函数将返回一个布尔值,
表示该身份证号码是否有效。
输入参数:
- cardNumber:类型为字符串(String),意义是输入的中国身份证号码,长度应为18位。
返回值:
- 类型为布尔值(Boolean),意义是如果输入的身份证号码完全有效,返回True;否则返回False。
示例:
1. IsValidIDCard["11010519491231002X"],返回True,因为这是一个完全有效的身份证号码。
2. IsValidIDCard["11010521011231002X"],返回False,因为出生年份超出合理范围。
3. IsValidIDCard["11010519491331002X"],返回False,因为月份不符合实际。
4. IsValidIDCard["11010519491232002X"],返回False,因为日期不符合实际。
5. IsValidIDCard["110105194912310021"],返回False,因为这是一个校验码错误的身份证号码。
*)
IsValidIDCard :=
Module[{weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2},
checkCodes = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"},
sum, remainder, checkDigit, year, month, day, dateValid},
If != 18,
Return];
(* 计算前17位数字与加权因子的乘积之和 *)
sum = 0;
For[i = 1, i <= 17, i++,
digit = FromDigits];
sum = sum + digit * weights[];
];
remainder = Mod;
checkDigit = StringTake;
(* 提取出生年份、月份和日期 *)
year = FromDigits];
month = FromDigits];
day = FromDigits];
(* 初始化日期有效性为True,然后根据条件修改 *)
dateValid = True;
If;
If;
If[(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && (day < 1 || day > 31), dateValid = False];
If[(month == 4 || month == 6 || month == 9 || month == 11) && (day < 1 || day > 30), dateValid = False];
If[month == 2,
If[(Mod == 0 && Mod != 0) || Mod == 0,
If[(day < 1 || day > 29), dateValid = False],
If[(day < 1 || day > 28), dateValid = False]
]
];
(* 综合校验码和日期有效性判断身份证是否有效 *)
dateValid && checkDigit === checkCodes[]
];
(* 单元测试 *)
(* 测试用例1:完全有效的身份证号码 *)
Print["测试用例1:", IsValidIDCard["11010519491231002X"]];
(* 测试用例2:校验码错误的身份证号码 *)
Print["测试用例2:", IsValidIDCard["110105194912310021"]];
(* 测试用例3:出生年份小于1900的身份证号码 *)
Print["测试用例3:", IsValidIDCard["11010518991231002X"]];
(* 测试用例4:出生年份大于2100的身份证号码 *)
Print["测试用例4:", IsValidIDCard["11010521011231002X"]];
(* 测试用例5:月份小于1的身份证号码 *)
Print["测试用例5:", IsValidIDCard["11010519490031002X"]];
(* 测试用例6:月份大于12的身份证号码 *)
Print["测试用例6:", IsValidIDCard["11010519491331002X"]];
(* 测试用例7:31天月份中日期大于31的身份证号码 *)
Print["测试用例7:", IsValidIDCard["11010519490132002X"]];
(* 测试用例8:30天月份中日期大于30的身份证号码 *)
Print["测试用例8:", IsValidIDCard["11010519490431002X"]];
(* 测试用例9:闰年2月日期大于29的身份证号码 *)
Print["测试用例9:", IsValidIDCard["11010520000230002X"]];
(* 测试用例10:非闰年2月日期大于28的身份证号码 *)
Print["测试用例10:", IsValidIDCard["11010519010229002X"]]; 代码写的太好了。还生成测试用例。
还有注释有说明。
比人工写的好。 本帖最后由 nyy 于 2025-3-5 13:41 编辑
nyy 发表于 2025-3-3 19:35
代码写的是好,但是有bug。
(*
函数功能:
该函数用于全面检验中国身份证号码的有效性,包括校验码是否正确、出生年份是否在合理范围内(1900至2100年)、
月份和日期是否符合实际情况。中国身份证号码由17位数字本体码和1位校验码组成。
校验码的计算方法是:将前17位数字分别乘以对应的加权因子(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2),
然后将乘积相加,再对结果取模11,根据模值得到对应的校验码字符(模值为0对应X,模值为1对应1,以此类推),
最后与输入的身份证号码的最后一位进行比较,判断校验码是否正确。
函数用法:
IsValidIDCard,传入一个字符串类型的身份证号码,函数将返回一个布尔值,
表示该身份证号码是否有效。
输入参数:
- cardNumber:类型为字符串(String,或者18位整数),意义是输入的中国身份证号码,长度应为18位。
返回值:
- 类型为布尔值(Boolean),意义是如果输入的身份证号码完全有效,返回True;否则返回False。
示例:
1. IsValidIDCard["11010519491231002X"],返回True,因为这是一个完全有效的身份证号码。
2. IsValidIDCard["11010521011231002X"],返回False,因为出生年份超出合理范围。
3. IsValidIDCard["11010519491331002X"],返回False,因为月份不符合实际。
4. IsValidIDCard["11010519491232002X"],返回False,因为日期不符合实际。
5. IsValidIDCard["110105194912310021"],返回False,因为这是一个校验码错误的身份证号码。
*)
IsValidIDCard :=
Module[{weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2},(*前17位权重*)
checkCodes = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"},(*0 1 2 3等余数所对应的校验码*)
sum, remainder, checkDigit, year, month, day, dateValid},
If,cardNumber=ToString];(*如果身份证号码是18位整数,则转化为字符串*)
If != 18,
Return];
(* 计算前17位数字与加权因子的乘积之和 *)
sum = 0;
For[i = 1, i <= 17, i++,
digit = FromDigits];(*此处有bug,原本是StringTake,表示提取前i个字符,而此处需要是第i个字符*)
sum = sum + digit * weights[];
];
remainder = Mod;(*求余数*)
checkDigit = StringTake;(*提取最后一位校验码*)
(* 提取出生年份、月份和日期 *)
year = FromDigits];
month = FromDigits];
day = FromDigits];
(* 初始化日期有效性为True,然后根据条件修改 *)
dateValid = True;
If;
If;
If[(month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && (day < 1 || day > 31), dateValid = False];
If[(month == 4 || month == 6 || month == 9 || month == 11) && (day < 1 || day > 30), dateValid = False];
If[month == 2,
If[(Mod == 0 && Mod != 0) || Mod == 0,
If[(day < 1 || day > 29), dateValid = False],
If[(day < 1 || day > 28), dateValid = False]
]
];
(* 综合校验码和日期有效性判断身份证是否有效 *)
dateValid && (checkDigit === checkCodes[])
];
(* 单元测试 *)
(* 测试用例1:完全有效的身份证号码 *)
Print["测试用例1:", IsValidIDCard["11010519491231002X"]];
(* 测试用例2:校验码错误的身份证号码 *)
Print["测试用例2:", IsValidIDCard["110105194912310021"]];
(* 测试用例3:出生年份小于1900的身份证号码 *)
Print["测试用例3:", IsValidIDCard["11010518991231002X"]];
(* 测试用例4:出生年份大于2100的身份证号码 *)
Print["测试用例4:", IsValidIDCard["11010521011231002X"]];
(* 测试用例5:月份小于1的身份证号码 *)
Print["测试用例5:", IsValidIDCard["11010519490031002X"]];
(* 测试用例6:月份大于12的身份证号码 *)
Print["测试用例6:", IsValidIDCard["11010519491331002X"]];
(* 测试用例7:31天月份中日期大于31的身份证号码 *)
Print["测试用例7:", IsValidIDCard["11010519490132002X"]];
(* 测试用例8:30天月份中日期大于30的身份证号码 *)
Print["测试用例8:", IsValidIDCard["11010519490431002X"]];
(* 测试用例9:闰年2月日期大于29的身份证号码 *)
Print["测试用例9:", IsValidIDCard["11010520000230002X"]];
(* 测试用例10:非闰年2月日期大于28的身份证号码 *)
Print["测试用例10:", IsValidIDCard["11010519010229002X"]];
bug的原因,我已经写在代码里面了。
digit = FromDigits];
这个表示提取前i个字符
digit = FromDigits];
这个表示提取第i个字符,
看来人工智能真的不智能呀!
看起来是很正确的代码,结果还要我给你根除bug。
页:
[1]
2