最近项目中用到统一信用代码的解析和校验,找了几个库都没找到特别合适的,于是在全国标准信息公共服务平台上查了下相关标准(GB 32100-2015),通过标准文件发现这个还引用了另外三个标准:GB/T 2260、GB 11714 和 GB/T 17710。然后又分别查了下这几个标准看起来还比较简单,想想不如自己实现一个,于是有了这个库:gb-util。
目前包含的标准有:
- GB 11643:公民身份号码(现行1999版)
- GB 11714:全国组织机构代码编制规则(现行1997版)
- GB 32100:法人和其他组织统一社会信用代码编码规则(现行2015版)
- GB/T 2260:中华人民共和国行政区划代码(现行2007版)
- GB/T 17710:信息技术、安全技术、校验字符系统(现行2008版)
- GB/T 5795:中国标准书号(现行2006版)
- ISO_7064:国际ISO标准校验字符系统(现行2003版)
其中
GB/T 17710
等同于ISO/IEC国际标准ISO/IEC 7064
,GB/T 5795
修改采用国际标准ISO 2108
。
ISO 7064 校验字符系统
校验码系统是产生校验码并校验包括校验码在内的字符串的一套规则。它可以防止在抄录和键入字符串时产生的错误。本标准规定了两类校验码系统:纯系统和混合系统。
纯系统
纯系统字符串满足如下公式的校验:
$$P®=\sum_{i=1}^{n}[a_{i}\times {r}^{(i-1)}]\equiv 1(\mathbf{mod} \ M)$$
其中:
- $n$ 指字符串的长度(包括校验码)
- $i$ 指字符位置序号(从右到左,包括校验码,最右端 $i=1$)
- $a_{i}$ 指第 $i$ 位上字符对应的数字值
- $r$ 指多项式的底数
- $M$ 指模数
纯系统计算校验码有两种方法:递归法和多项式法。其实就是根据多项式展开形式不同得出的两种方法。
多项式法是把 $P®$ 表示为:
$$P®=\sum_{i=1}^{n}[a_{i}\times W_{i}]\equiv 1(\mathbf{mod} \ M)$$
- 其中 $W_{i}={r}^{(i-1)} \ \mathbf{mod} \ M$ 称为加权因子
如果是一位校验码则 $a_{1}$ 是校验码,根据上面式子可以得出:
$$a_{1}=M + 1 - (\sum_{i=2}^{n}[a_{i}\times W_{i}] \ \mathbf{mod} \ M)$$
递归法是把 $P®$ 表示为如下形式计算(也称秦九韶算法):
$$P®=(\cdots((a_{n}r+a_{n-1})r + a_{n-2})r + \cdots + a_{2})r+a_{1}$$
将上面公式转为递归公式(从左到右依次处理,即 $j=1,2,\cdots n$)为:
$$P_{1}=0$$ $$P_{j+1}=(P_{j} + a_{n-j+1})\times r$$
递归法适合对长度不固定的字符串计算校验码,而对于长度固定的字符串(如身份证、统一信用代码等)用多项式法比较好,因为固定长度可以提前把 $W_{i}$ 算出来保存到数组里,这样可以减少计算量。
混合系统
纯系统字符串满足如下公式的校验:
$$(\cdots((((M+a_{n})||{M}\times 2)|{M+1} + a_{n-1})||{M}\times 2)|{M+1}+\cdots+a_{1})|_{M}=1$$
其中:
- $M$ 和 $M+1$ 指两个模数,$M$ 是字符集中字符的数量(如 0-9 字符集中 $M=10$)
- $||_{M}$ 指除以 $M$ 后的余数,如果为 0 则用 $M$ 代替
- $|_{M+1}$ 指除以 $M+1$ 后的余数
由上面公式可以看出混合系统只能采用递归方法,将上面公式转为递归公式(从左到右依次处理,即 $j=1,2,\cdots n$)为:
$$P_{1}=M$$ $$S_{j}=P_{j}|{M+1}+a{n-j+1}$$ $$P_{j+1}=S_{j}||_{M}\times2$$
使用方法
import { ISO_7064 } from 'gb-util';
// Pure systems
ISO_7064.mod11_2('0794'); // => '0'
ISO_7064.mod37_2('1234ABCD'); // => 'V'
ISO_7064.mod97_10('794'); // => '44'
ISO_7064.mod661_26('ABCD'); // => 'KN'
ISO_7064.mod1271_36('ISO79'); // => '3W'
// Hybrid systems
ISO_7064.mod11_10('0794'); // => '5'
ISO_7064.mod27_26('JEJLMGJ'); // => 'S'
ISO_7064.mod37_36('B7Q3SFTUSH2QN7BIXBPMNZAM'); // => 'I'
GB 11643 公民身份号码
本标准规定了中国公民身份证号码的编码方法,校验码采用标准的 ISO 7064
中的 MOD 11-2
校验码系统。号码格式为:
6位行政区划码 + 8位出生日期 + 3位顺序码 + 1位校验码
其中行政区划码来自
GB/T 2260
标准,出生日期格式为YYYYMMDD
,顺序码奇数分配给男性偶数分配给女性。
根据 ISO 7064
中的多项式法可以计算加权因子($W_{i}=2^{i-1} \mod 11$)如下表:
$i$ | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$W_{i}$ | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 | 6 | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 |
使用方法:
import { GB_11643 } from 'gb-util';
GB_11643.compute('11010519491231002'); // => 'X'
GB_11643.isValid('11010519491231002X'); // => true
GB_11643.parse('11010519491231002X');
/* => {
areaCode: '110105',
birth: '1949-12-31',
order: 2,
sex: 0
} */
GB 11714 全国组织机构代码编制规则
本标准校验公式为:
$$P(2)=\sum_{i=1}^{9}[a_{i}\times {2}^{(i-1)}]\equiv 0(\mathbf{mod} \ 11)$$
则校验码 $a_{1}$ 为:
$$a_{1}=11 - (\sum_{i=2}^{9}[a_{i}\times W_{i}] \ \mathbf{mod} \ 11)$$
计算加权因子如下表:
$i$ | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---|---|---|---|---|---|---|---|---|---|
$W_{i}$ | 3 | 7 | 9 | 10 | 5 | 8 | 4 | 2 | 1 |
使用方法:
import { GB_11714 } from 'gb-util';
GB_11714.compute('D2143569'); // => 'X'
GB_11714.isValid('D2143569X'); // => true
GB 32100 法人和其他组织统一社会信用代码编码规则
统一社会信用代码构成如下:
1位登记管理部门代码 + 1位机构类别代码 + 6位行政区划码 + 9位组织机构代码 + 1位校验码
本标准校验公式为:
$$a_{1} + \sum_{i=2}^{18}[a_{i}\times {3}^{(18-i)}]\equiv 0(\mathbf{mod} \ 31)$$
则校验码 $a_{1}$ 为:
$$a_{1}=31 - (\sum_{i=2}^{18}[a_{i}\times W_{i}] \ \mathbf{mod} \ 31)$$
$i$ | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$W_{i}$ | 1 | 3 | 9 | 27 | 19 | 26 | 16 | 17 | 20 | 29 | 25 | 13 | 8 | 24 | 10 | 30 | 28 |
使用方法:
import { GB_32100 } from 'gb-util';
GB_32100.compute('91350100M000100Y4'); // => '3'
GB_32100.isValid('91350100M000100Y43'); // => true
GB_32100.parse('91350100M000100Y43');
/* => {
adminDept: '工商',
areaCode: '350100',
id: 'M000100Y4',
type: '企业'
} */
GB/T 2260 中华人民共和国行政区划代码
很多开源的行政区划库有的数据不是最新的、有的数据只有最新的,全面的很少。
gb-util
包含了最新、最全的行政区划代码数据,既可以查最新也可以查历史数据,还可以查地区是否改过名字、历史上用过哪些名字。
使用方法如下:
import { GB_T_2260 } from 'gb-util';
GB_T_2260.getAreaName('110000'); // => '北京市'
GB_T_2260.getAreaCode('北京市'); // => ['110000']
GB_T_2260.isRevoked('372401'); // => true
GB_T_2260.getUsedNames('220281'); // => ['蛟河市', '桦甸市']
GB_T_2260.getArea('110105');
/* => {
code: '110105',
name: '朝阳区',
province: '北京市',
city: '北京市',
county: '朝阳区',
revoked: false,
usedNames: []
} */
GB_T_2260.getAreaTree();
// => [{ code: '130000', name: '河北省', children: [...] }, ...]
GB_T_2260.getProvinces();
// => [{ code: '110000', name: '北京市' }, ...]
GB_T_2260.getCities('130000');
// => [{ code: '130100', name: '石家庄市' }, ...]
GB_T_2260.getCounties('130100');
// => [{ code: '130102', name: '长安市' }, ...]
GB/T 5795:中国标准书号
本标准规定了图书的 ISBN 编码规则,修改采用 ISO 国际标准 ISO 2108
,包含现行的 13 位和历史的 10 位两种编码方法。
13位 ISBN 编码结构如下:
3位EAN.UCC前缀 + 组区号 + 出版者号 + 出版序号 + 1位校验码
13位 ISBN 校验码的权重 $W_{i}$:当 $i$ 为奇数时值为
1
,偶数时值为3
。模数为10
。
10 位 ISBN 编码结构如下:
组区号 + 出版者号 + 出版序号 + 1位校验码
10 位 ISBN 校验码的权重 $W_{i}=i$,模数为
11
。
使用方法:
import { GB_T_5795 } from 'gb-util';
GB_T_5795.compute('4873113369'); // => '9'
GB_T_5795.compute('978-4-87311-336-4'); // => '4'
GB_T_5795.isValid('978-4-87311-336-4'); // => true
GB_T_5795.parse('9784873113364');
/* => {
isIsbn10: false,
isbn10: '4873113369',
isbn13: '9784873113364',
prefix: '978',
group: '4',
groupName: 'Japan',
publisher: '87311',
article: '336',
isbn10h: '4-87311-336-9',
isbn13h: '978-4-87311-336-4'
} */
👍
数学公式没法显示,给 nodeclub
提了 PR:feat: add math support,有谁帮忙处理下么?@fengmk2 @alsotang
公式修复前先贴个知乎的文章链接吧:https://zhuanlan.zhihu.com/p/358015326
PS: 知乎的编辑器对 Markdown 支持也是差,表格只能用图片了。