需求
其实这是一道算法题:
先看看集装箱编号的规则说明
一、 标准箱号构成基本概念:采用ISO6346(1995)标准。 标准集装箱箱号由11位编码组成,包括三个部分:
1、 第一部分由4位英文字母组成。前三位代码 (Owner Code) 主要说明箱主、经营人,第四位代码说明集装箱的类型。列如CBHU 开头的标准集装箱是表明箱主和经营人为中远集运。
2、 第二部分由6位数字组成。是箱体注册码(Registration Code), 用于一个集装箱箱体持有的唯一标识。
3、 第三部分为校验码(Check Digit)由前4位字母和6位数字经过校验规则运算得到,用于识别在校验时是否发生错误。即第11位数字。 根据校验规则箱号的每个字母和数字都有一个运算的对应值。箱号的前10位字母和数字的对应值从0到Z对应数值为0到38,11、22、33不能对11取模数,所以要除去。
2、第N位的箱号对应值再分别乘以2N-1 (N=1,2,3………..10) 例如:箱号为CBHU3202732的集装箱它的第1位代码为C, 它的代码值=代码的对应值×21-1 =13×1=13。 类推第2位代码为B 它的代码值=代码的对应值×22-1 =12×2=24
以此类推得到箱号前10位代码的代码值。 将前10位的代码值乘积累加后对11取模 箱号为CBHU3202732的集装箱前10位箱号的代码累加值=4061,取11的模后为2,就是这个箱号第11位的识别码的数值。 以此类推,就能得到校验码 集装箱编号是集装箱全球唯一识别标识 根据ISO6346:1995 《集装箱--代码、识别和标记》标准,集装箱校验码算法如下:
集装箱编号共11位,前四位是字母,最后一位为校验码,举例如◎◎◎◎×××××××。 字母取数值规则为:A=10,B至K依次取12至21,L至U依次取23至32,V至Z依次取34至38。 箱号第一位的值乘以2的0次幂,第二位乘以2的1次幂,...,第十位乘以2的9次幂,然后求和。 其和除以11的余数即为校验码的值。(注:当余数为10时,校验码也为
集装箱编号是集装箱全球唯一识别标识 根据ISO6346:1995 《集装箱--代码、识别和标记》标准,集装箱校验码算法如下: 集装箱编号共11位,前四位是字母,最后一位为校验码,举例如◎◎◎◎×××××××。 字母取数值规则为:A=10,B至K依次取12至21,L至U依次取23至32,V至Z依次取34至38。 箱号第一位的值乘以2的0次幂,第二位乘以2的1次幂,...,第十位乘以2的9次幂,然后求和。 其和除以11的余数即为校验码的值。(注:当余数为10时,校验码也为
代码
@Override
public void verifyCntrCode(String cntrNo ) throws Exception {
result.setAck(EnumAck.Failure);
if (StringUtils.isEmpty(cntrNo)) {
System.out.println("装箱号不能为空!");
}
int length = cntrNo.length();
if (length != 11) {
System.out.println("总长度非11位长!");
}
String sub1 = StringUtils.substring(cntrNo, 0, 4);
if (!sub1.matches("[A-Z]+")) {
System.out.println("第一部分非大写字母!");
}
String sub2 = StringUtils.substring(cntrNo, 4, length-1);
if(!sub2.matches("[0-9]*")){
System.out.println("第二部分非数字!");
}
String sub3 = StringUtils.substring(cntrNo, length-1, length);
if(!sub3.matches("[0-9]*")){
System.out.println("第二部分非数字!");
}
//定义一个字符串,集装箱编号的每个字符必定出自这串字符,其中11,22,33用?代替,获取对应值,满足0-38
String charCode = "0123456789A?BCDEFGHIJK?LMNOPQRSTU?VWXYZ";
char[] codeChars = cntrNo.toCharArray();//将接收到的字符串转换为字符数组,方便后续遍历
int num = 0;//初始化用于规则计算后累计的变量,用于计算结束后%第11位
for (int i = 0; i < 10; i++) {
int idx = charCode.indexOf(codeChars[i]);//遍历取出第i个字符,并从charCode字符串中查找这个字符所在位置,这个位置的值就是对应值
if (idx == -1 || charCode.charAt(idx)=='?') {//如果查找不到或者找到替代符号(?)一样,那么这个字符不是规则中所要求的字符,需要校验的字符串不符合集装箱号的规则,退出循环
System.out.println("不符合集装箱号的规则");
break;
}
idx = (int) (idx * Math.pow(2, i));//这里的意思应该是说对应值*2的(n-1)次方;原文表达(2、第N位的箱号对应值再分别乘以2N-1 (N=1,2,3………..10))是误导的关键
num += idx;//累加
}
num = (num % 11) % 10;//取模11
if(!Integer.parseInt(String.valueOf(codeChars[10]))== num){
System.out.println("第11位校验码未通过验证");
}
System.out.println("验证码全部通过规则验证!");
}