根据《中国银联2.0》标准 - Q/CUP 002-2004 提供的算法 Luhn计算模10“隔位2倍加”校验数的公式
计算步骤如下:
步骤1:从右边第1个数字(低序)开始每隔一位乘以 2 。
步骤2:把在步骤1中获得的乘积的各位数字与原号码中未乘2的各位数字相加。
步骤3:从邻近的较高的一个以0结尾的数中减去步骤2中所得到的总和 [这相当于求这个总和的低位数字(个位数)的“ 10的补数 ”], 如果在步骤2得到的总和是以零结尾的数(如30、40等等),则校验数字就是零。
[例]:
无校验数的卡号655002 0001 00000328 步骤
6 5 5 0 0 2 0 0 0 1 0 0 0 0 0 3 2 8 1 x2 x2 x2 x2 x2 x2 x2 x2 x2
10 0 4 0 2 0 0 6 16
6 + 1 + 0 + 5 + 0 + 0 + 4 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 6 + 2 + 1 + 6 = 33 2
40 – 33 = 7 3
即校验为 7 带有校验数的卡号为:655002 0001 00000328 7(银联要求的卡号是13-19位,此程序暂时满足19位卡号的计算,19位以下的有待修改)功能:检查19位的银行卡号码的有效性运行环境:Red Hat Enterprise Linux AS release 3 、AIX Version 5 操作系统上测试通过编译命令:cc -o card card.c执行命令:./card源代码:
/************************************************************FileName: card.cAuthor: yuanfen127Date: 2005年12月01日Description: 银行卡号码的有效性检查程序Version: 1.0Function List: 1. int CreatBit(char *cdno, int length) 根据前面length-1位长度生成最后校验位 2. int iCheckBit(char *sbuf) 调用CreateBit生成校验位和输入的比较History: <author> <time> <version > <desc>***********************************************************/#include <stdio.h>#include <string.h>
main(){ char card_no[20];
printf("请输入19位卡号:"); scanf("s",card_no);
printf("卡号:%s/n",card_no);
/*CreatBit(card_no,strlen(card_no)-1);*/ if ( strlen(card_no) < 19 ) { printf("卡号长度错误/n"); return -1; }
if ( 0 != iCheckBit(card_no) ) { printf("卡号错误!/n"); } else { printf("卡号正确!/n"); }}
int CreatBit(char *cdno, int length){ int CI[18]={1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2}; int i,d,result; int chk_dig=0;
if ( strlen(cdno) < length) { printf("输入的长度错,长度=%d/n",strlen(cdno)); return -1; } for ( i=0; i<length; i++ ) { d = cdno[i]-48; result = d * CI[i]; chk_dig += result/10 + result; } chk_dig = 10 - chk_dig; chk_dig = (chk_dig==10) ? 0 : chk_dig; cdno[length] = chk_dig + 48;
printf("检验位:%d/n",chk_dig); return 0;}
int iCheckBit(char *sbuf){ char cardbuf[19]; int l_len;
memcpy( cardbuf, sbuf, 19 ); l_len = strlen(sbuf); l_len = l_len > 19 ? 19 : l_len ; if( (CreatBit(cardbuf, l_len - 1 ) != 0) || memcmp(sbuf, cardbuf, l_len)) { return(-1); } return(0);}