前言:系统用图书的ISBN编码作为查询条件,由于套装书或其它情况导致ISBN编码可能重复,针对这种情况图书馆自定义了一批ISBN编码,因此需要区分是否为自定义的ISBN编码。
由于ISBN编码有一套对应的生成规则,并且各个图书馆的自定义编码不相同,所以准备利用ISBN编码生成规则使用java程序处理
直接上代码有兴趣的可以看看下边的内容:
package com.isbn.core.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.UnknownFormatConversionException;
import java.util.regex.Pattern;
/**
* @author ruqiang
* @version 1.0.0
* @className: IsbnUtil
* @Description ISBN编码校验工具类
* @create 2019/11/26
*/
@Slf4j
public class IsbnUtil {
/**
* 所需值
*/
private static final String FORMAT_TEN = "^[0-9]{%s}[0-9X]{1}$";
private static final String FORMAT_THIRTEEN = "^[0-9]{%s}$";
private static final Integer ZERO = 0;
private static final Integer ONE = 1;
private static final Integer TWO = 2;
private static final Integer THREE = 3;
private static final Integer NINE = 9;
private static final Integer TEN = 10;
private static final Integer ELEVEN = 11;
private static final Integer THIRTEEN = 13;
private static final String X = "X";
public static Boolean checkIsbn(String isbn) {
//获取计算加权和所需要的值
String substring = isbn.substring(ZERO, isbn.length() - ONE);
//加权和S
Integer s = ZERO;
//由于ISBN,10位和13位校验方法不相同,先进行区分
if (Pattern.matches(String.format(FORMAT_TEN, NINE), isbn)) {
//获取比较值并转化为Integer
Integer comparison = null;
String comparisonStr = null;
try {
comparison = Integer.parseInt(isbn.substring(isbn.length() - 1));
} catch (NumberFormatException e) {
comparisonStr = X;
}
//转化为Integer数组
Integer[] isbnArr;
try {
isbnArr = (Integer[]) ConvertUtils.convert(substring.split(""), Integer.class);
} catch (UnknownFormatConversionException e) {
log.error("ISBN编码转化Integer数组失败:{}", e);
return false;
}
//递减值j
Integer j = TEN;
//计算加权和:即将ISBN号码前9位数字分别乘以10, 9, 8, 7, 6, 5, 4, 3, 2,然将它们相加,得到加权和
for (int i = ZERO; i < isbnArr.length; i++, j--) {
s = isbnArr[i] * j + s;
}
//取余数M
Integer m = s % ELEVEN;
//计算校验码N
Integer N = ELEVEN - m;
if (StringUtils.isNotEmpty(comparisonStr)) {
return N.equals(TEN) ? true : false;
} else {
return ONE.equals(N) ? ZERO.equals(comparison) ? true : false : comparison.equals(N) ? true : false;
}
}
if (Pattern.matches(String.format(FORMAT_THIRTEEN, THIRTEEN), isbn)) {
//获取比较值并转化为Integer
Integer comparison = Integer.parseInt(isbn.substring(isbn.length() - 1));
//转化为Integer数组
Integer[] isbnArr = (Integer[]) ConvertUtils.convert(substring.split(""), Integer.class);
//计算加权和:用1分别乘ISBN的前12位中的奇数位,用3乘以偶数位,然后将两者相加,即得到加权和
for (int i = ZERO; i < isbnArr.length; i++) {
s=i%TWO==ZERO?isbnArr[i]*ONE+s:isbnArr[i]*THREE+s;
}
//取余数M
Integer m = s % TEN;
//计算校验码N
Integer N = TEN - m;
return N.equals(TEN) ? comparison.equals(ZERO) ? true : false : comparison.equals(N) ? true : false;
}
return false;
}
public static void main(String[] args) {
System.out.println(String.format("10位测试结果:%s", checkIsbn("7309045475")));
System.out.println(String.format("13位测试结果:%s", checkIsbn("9787115275790")));
}
}
计算方式
ISBN书号校验码的计算方法
一、10位书号校验码的计算方法
10位书号校验码只有一位,从0到10,10由X代替。其计算方法为:
第一步 计算加权和:即将ISBN号码前9位数字分别乘以10, 9, 8, 7, 6, 5, 4, 3, 2,然将它们相加,得到加权和(设该加权和为S);
第二步 计算余数:即将第一步得到的和(S)除以11,取其余数(设该余数为M);
第三步 计算校验码:用11减去第二步得到的余数(M),所得之差就是计算校验码的基础(N)。
【说明】如果所得之差N为10,校验码是字母X;如果所得之差N为1,校验码是数字0;如果所得之差N为其他数字,则校验码就是该数字。
【举例】假设某ISBN号码前9位是:7-309-04547,其校验码计算方法如下:
第一步:计算加权和(S):S=7×10+3×9+0×8+9×7+0×6+4×5+5×4+4×3+7×2 = 226
第二步:计算余数(M):M = 226÷11余6
第三步:计算校验码(N):N = 11 ? 6 = 5
校验码为5。
二、13位书号校验码的计算方法
13位ISBN的最后一位校验位的加权算法与10位ISBN的算法不同。具体计算方法为:
第一步 计算加权和:用1分别乘ISBN的前12位中的奇数位,用3乘以偶数位,然后将两者相加,即得到加权和(设该加权和为S);
第二步 计算余数:即将第一步得到的加权和除以10,取其余数(设该余数为M);
第三步 计算校验码:即用10减去第二步得到的余数,所得之差就是计算校验码的基础(N)。
【说明】如果所得之差N为10,则校验码取0。
【举例】假设某13位ISBN号码前12位是:987-7-309-04547
第一步:计算加权和(S):S=9×1+8×3+7×1+7×3+3×1+0×3+9×1+0×3+4×1+5×3+4×1+7×3 = 117
第二步:计算余数(M):M = 117÷10 余数为7
第三步:计算校验码(N):N = 10 ? 7 = 3
故本书的第13位ISBN的校验码是3。
ISBN图书编码简介:
国际标准书号(International Standard Book Number),简称ISBN,是专门为识别图书等文献而设计的国际编号。
采用ISBN编码系统的出版物有:图书、小册子、缩微出版物、盲文印刷品等。
2007年1月1日前,ISBN由10位数字组成,分四个部分:
- 组号(国家、地区、语言的代号)
- 出版者号
- 书序号
- 检验码
2007年1月1日起,实行新版ISBN,新版ISBN由13位数字组成,分为5段,即在原来的10位数字前加上3位EAN(欧洲商品编号)图书产品代码“978”。在联机书目中ISBN可以作为一个检索字段,从而为用户增加了一种检索途径。
旧版,即2007年1月1日前
第一组号码段,组号(国家、地区、语言的代号)
最短的是一位数字,最长的达五位数字如不丹:99936。
代码 | 含义 | 代表国家 |
---|---|---|
0和1 | 代表英语 | 英国、美国、澳大利亚、加拿大等 |
2 | 代表法语 | 法国、瑞士、比利时等 |
3 | 代表德语 | 德国、奥地利等 |
4 | 代表日本 | 日本 |
5 | 代表俄语 | 俄罗斯 |
7 | 代表中国 | 中国 |
第二组号码段,是出版社代码,由其隶属的国家或地区ISBN中心分配,允许取值范围为2-5位数字。
第三组号码是书序码,由出版社自己给出,书序号是定长的数字9,减去组号、出版社代码所占的位数,就是书序码的位数。最短的一位,最长的六位。
第四组号码段,是校验码,其数值由前九位数字依次以10~2加权之和并以11为模计算得到。
校验方式
将ISBN前九位数字依序分别乘以从10到2的数目,将其乘积相加,总和用11去除;若无余数则检查号码为“0”;若有余数,则以11减去余数,所得差数即为检查号,若差数为10,则以代表罗马数字10的“X”来表示。
新版,即2007年1月1日起,在最前面多了一组EAN
EAN:European Article Number(欧洲商品号),国际标准书号中心于2004年决定在国际标准书号的基础上再添加一组三位数字在最前,即将现有的10位书号前面加上前缀号“978”或“979”及重新计算稽核号,以转换为新的13位格式,与13位欧洲商品编码相同。该计划于2007年1月1日实施。
转化:
ISBN-10与ISBN-13之间的相互转换算法
1.从ISBN-10转换为ISBN-13
下面以ISBN 7-302-12260-1为例,介绍从ISBN-10转换为ISBN-13的具体步骤。
(1)从ISBN-10中去除校验码(即最后一位),得到一个9位数字7-302-12260
(2)在这个9位数字之前添加前缀978,得到12位数字978-7-302-12260
(3)使用模为10的校验码计算方法重新计算校验码。使用从第2步得到的12位数字,每位乘以相应的加权因子。将结果相加,得和为81将这个和除以模数10,得余数为1,用标准模数减去余数就可以得出校验码。这里10减1得9把校验码添加到由第2步生成的12位数字后,于是,转换成的ISBN-13就是978-7-302-12260-9
具体算法如下:91+73+81+73+31+03+21+13+21+23+61+03=81
81/10=8,余数为1,10-1=9
注意:这个公式有一个例外,当余数为0时,校验码即为0。
2.从以978打头的ISBN-13转换成ISBN-10
注意:只有前级为978的ISBN-13才有对应的ISBN-10。
下面以转换成的ISBN 978-7-302-12260-9为例,转换回ISBN-10。
(1)从ISBN-13中删除前缀978和校验码,得到一个9位数字,即为7-302-12260
(2)重新计算校验码。使用从上面第1步中得到的9位数字,将每位数字与表2中相应的加权因子相乘。
将乘积相加,得和为153将这个和除以11,得余数为10,用11减去这个余数,结果就是校验码。这里,11减去10得1,把校验码添加到从第1步中得到的9位数字的后面,于是,转换成的ISBN-10就是7-302-12260-1
具体算法如下:710+39+08+27+16+25+24+63+0*2=153
153/11=13,余数为10,11-10=1
注意:如果校验码的值为10,则应用罗马数字X表示