校验集装箱号

标题校验集装箱号: CBHU3202732

/**
 * 校验集装箱号: CBHU3202732
 * 标准箱号构成基本概念:采用ISO6346(1995)标准。
 * 标准集装箱箱号由11位编码组成,包括三个部分:
 * 1、 第一部分由4位英文字母组成。前三位代码 (Owner Code) 主要说明箱主、经营人,第四位代码说明集装箱的类型。列如CBHU 开头的标准集装箱是表明箱主和经营人为中远集运。
 * 2、 第二部分由6位数字组成。是箱体注册码(Registration Code),用于一个集装箱箱体持有的唯一标识。
 * 3、 第三部分为校验码(Check Digit)由前4位字母和6位数字经过校验规则运算得到,用于识别在校验时是否发生错误。即第11位编号。
 * 根据校验规则箱号的每个字母和数字都有一个运算的对应值。箱号的前10位字母和数字的对应值从0到Z对应数值为10到38,11、22、33不能对11取模数,所以要除去
 * 第N位的箱号对应值再分别乘以2的N-1次方 (N=1,2,3………..10)
 * 例如:箱号为CBHU3202732的集装箱它的第1位代码为C,
 * 它的代码值=代码的对应值×2的0次方 =13×1=13。
 * 类推第2位代码为B
 * 它的代码值=代码的对应值×2的1次方 =12×2=24
 * 以此类推得到箱号前10位代码的代码值。
 * 将前10位的代码值乘积累加后对11取模
 * 箱号为CBHU3202732的集装箱前10位箱号的代码累加值=4061,取11的模后为2,就是这个箱号第11位的识别码的数值。
 *
 * @param containerNo
 * @throws Exception
 */
public void verifyContainerNo(String containerNo) {
    //集装箱号不能为空!
    Assert.notNull(containerNo, messageUtils.getMessage("CONTAINERNO_CAN_NOT_NULL"));
    //总长度非11位长!
    int length = containerNo.length();
    Assert.isFalse(length != 11, messageUtils.getMessage("THE_TOTAL_LENGTH_IS_NOT_11_BITS_LONG"));
    //第一部分非大写字母!
    String sub1 = StringUtils.substring(containerNo, 0, 4);
    Assert.isFalse(!sub1.matches("[A-Z]+"), messageUtils.getMessage("THE_FIRST_PART_IS_NOT_CAPITAL_LETTERS"));
    //第二部分非数字!
    String sub2 = StringUtils.substring(containerNo, 4, length - 1);
    Assert.isFalse(!sub2.matches("[0-9]*"), messageUtils.getMessage("THE_SECOND_PART_IS_NOT_NUMERICAL"));
    //第三部分非数字!
    String sub3 = StringUtils.substring(containerNo, length - 1, length);
    Assert.isFalse(!sub3.matches("[0-9]*"), messageUtils.getMessage("THE_SECOND_PART_IS_NOT_NUMERICAL"));
    //定义一个字符串,集装箱编号的每个字符必定出自这串字符,其中11,22,33用?代替,获取对应值,满足0-38
    String charCode = "0123456789A?BCDEFGHIJK?LMNOPQRSTU?VWXYZ";
    //将接收到的字符串转换为字符数组,方便后续遍历
    char[] codeChars = containerNo.toCharArray();
    //初始化用于规则计算后累计的变量,用于计算结束后%第11位
    int num = 0;

    for (int i = 0; i < 10; i++) {
        //遍历取出第i个字符,并从charCode字符串中查找这个字符所在位置,这个位置的值就是对应值
        int idx = charCode.indexOf(codeChars[i]);
        //遍历取出第i个字符,并从charCode字符串中查找这个字符所在位置,这个位置的值就是对应值
        if (idx == -1 || charCode.charAt(idx) == '?') {
            System.out.println(messageUtils.getMessage("DOES_NOT_COMPLY_WITH_THE_CONTAINER_NUMBER_RULES"));
            break;
        }
        //这里的意思应该是说对应值*2的(n-1)次方;原文表达(2、第N位的箱号对应值再分别乘以2N-1 (N=1,2,3………..10))是误导的关键
        idx = (int) (idx * Math.pow(2, i));
        //累加
        num += idx;
    }
    //取模11
    num = (num % 11) % 10;
    if (!(Integer.parseInt(String.valueOf(codeChars[10])) == num)) {
        System.out.println(messageUtils.getMessage("THE_11TH_BIT_CHECK_CODE_FAILS_THE_VERIFICATION"));
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值