在不查询数据库的情况下,每个会员登录进来会生成一个数字字母组合不重复的会员卡号。
效果图如下:
当我们要将一个庞大的数据进行编号时,而编号有位数限制,比如5位的车牌号、10位的某证件号码、订单流水号、短网址等等,我们可以使用36进制计算出符合位数的不重复的编号。
我们将0-Z(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)分别代表数值0-35,如字母Z代表35。这样的话我要得到一个5位的编号,最大信息量就是36的5次方了,36^5 = 60466176,即最大的5位编号相当于10进制的数字:60466176。
本文中为了做演示,我们假定某俱乐部发放一批10位的会员卡号,会员卡号由3位城市编号+5位卡号编码+2位校验码组成。城市编号用区号表示,如755代表深圳,5位卡编号则由36进制的卡编号组成,后面两位校验码则是通过一定的算法生成的,校验码的用处是可以验证卡号的合法性。这样的话,我们生成的10位卡号相当于最大能满足6000多万会员卡号,并且是不重复唯一的卡号。
PHP
我们使用PHP进行进制转换,10进制转36进制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
class
Code {
//密码字典
private
$dic
=
array
(
0=>
'0'
, 1=>
'1'
, 2=>
'2'
, 3=>
'3'
, 4=>
'4'
, 5=>
'5'
, 6=>
'6'
, 7=>
'7'
, 8=>
'8'
,
9=>
'9'
, 10=>
'A'
, 11=>
'B'
, 12=>
'C'
, 13=>
'D'
, 14=>
'E'
, 15=>
'F'
, 16=>
'G'
, 17=>
'H'
,
18=>
'I'
,19=>
'J'
, 20=>
'K'
, 21=>
'L'
, 22=>
'M'
, 23=>
'N'
, 24=>
'O'
, 25=>
'P'
, 26=>
'Q'
,
27=>
'R'
,28=>
'S'
, 29=>
'T'
, 30=>
'U'
, 31=>
'V'
, 32=>
'W'
, 33=>
'X'
, 34=>
'Y'
, 35=>
'Z'
);
public
function
encodeID(
$int
,
$format
=8) {
$dics
=
$this
->dic;
$dnum
= 36;
//进制数
$arr
=
array
();
$loop
= true;
while
(
$loop
) {
$arr
[] =
$dics
[
bcmod
(
$int
,
$dnum
)];
$int
=
bcdiv
(
$int
,
$dnum
, 0);
if
(
$int
==
'0'
) {
$loop
= false;
}
}
if
(
count
(
$arr
) <
$format
)
$arr
=
array_pad
(
$arr
,
$format
,
$dics
[0]);
return
implode(
''
,
array_reverse
(
$arr
));
}
public
function
decodeID(
$ids
) {
$dics
=
$this
->dic;
$dnum
= 36;
//进制数
//键值交换
$dedic
=
array_flip
(
$dics
);
//去零
$id
= ltrim(
$ids
,
$dics
[0]);
//反转
$id
=
strrev
(
$id
);
$v
= 0;
for
(
$i
= 0,
$j
=
strlen
(
$id
);
$i
<
$j
;
$i
++) {
$v
=
bcadd
(
bcmul
(
$dedic
[
$id
{
$i
}
], bcpow(
$dnum
,
$i
, 0), 0),
$v
, 0);
}
return
$v
;
}
}
|
我们定义Code类,先定义密码字典,即0-Z分别对应的数值,方法encodeID($int, $format)中参数$int表示数字,$format表示位数长度,比方encodeID(123456789,5)表示将数字123456789转换成5位的36进制编号,而方法decodeID($ids)用于将36进制的编号转换成10进制的编号。
我们可以这样来生成卡号:
1
2
|
$code
=
new
Code();
$card_no
=
$code
->encodeID(888888,5);
|
如上,我们就可以得到一个5位的卡编号,它实际代表着卡号是888888(6个8)的会员编号,而实际进行转换后是5位编号:0J1VC。
接着,我们将城市编号和校验码加上,城市编号是已经定义好的,校验码则通过一定的算法取得,本例中,我们使用简单的算法:将前三位城市编号和五位卡编号进行md5加密,然后取md5值的前2位作为校验码,这样就得到了编号后面的两位校验码。
1
2
3
4
|
$card_pre
=
'755'
;
$card_vc
=
substr
(md5(
$card_pre
.
$card_no
),0,2);
$card_vc
=
strtoupper
(
$card_vc
);
echo
$card_pre
.
$card_no
.
$card_vc
;
|
实际应用中,可以通过数据库得到10进制的编号,保证编号唯一,再将上述代码组合,最终生成一个10位的不重复的会员卡号。