PHP realizes the generation of unique numbers (36 ary non duplicate numbers)

  • 2021-07-06 10:26:07
  • OfStack

When we want to number a huge piece of data, and the number has a number limit, such as a 5-digit license plate number, a 10-digit certificate number, an order serial number, a short website address, etc., we can use the 36-digit system to calculate the non-duplicate number that matches the number.

We refer to 0-Z (0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ) for the values 0-35, such as the letter Z for 35. In this case, I want to get a 5-digit number, and the maximum amount of information is 36 to the fifth power, 36 5 = 60466176, that is, the maximum 5-digit number is equivalent to the decimal number 60466176.
In this paper, for demonstration, we assume that a club issues a batch of 10-digit membership card numbers, which consist of 3-digit city number +5-digit card number code +2-digit check code. City number is represented by area code. For example, 755 stands for Shenzhen, 5-digit card number is composed of 36-digit card number, and the latter two-digit check code is generated by 1-fixed algorithm. The purpose of check code is to verify the legitimacy of card number. In this way, the 10-digit card number generated by us is equivalent to the card number that can meet more than 60 million membership numbers at most, and it is a card number that does not repeat only one.

PHP Implementation

We use PHP for binary conversion, from 10 to 36.


class Code {
    // Cryptographic dictionary
    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; // Binary number
        $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; // Binary number
        // Key-value exchange
        $dedic = array_flip($dics);
        // Zero removal
        $id = ltrim($ids, $dics[0]);
        // Reversal
        $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;
    }
 
}

We define the Code class, first define the cryptographic dictionary, that is, the values corresponding to 0-Z. In the method encodeID ($int, $format), the parameter $int represents the number, and $format represents the bit length. For example, encodeID (123456789, 5) represents the conversion of the number 123456789 into a 5-digit 36-digit number, while the method decodeID ($ids) is used to convert the 36-digit number into a 10-digit number.
We can generate the card number like this:


$code = new Code();
$card_no = $code->encodeID(888888,5);

As above, we can get a 5-digit card number, which actually represents the member number with the card number 888888 (6 8s), and the actual 5-digit number after conversion: 0J1VC.
Then, we add the city number and the check code. The city number has been defined, and the check code is obtained by a definite algorithm. In this example, we use a simple algorithm: encrypt the first three city numbers and five card numbers by md5, and then take the first two digits of md5 as the check code, thus obtaining the two check codes after the number.


$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;

In practical application, we can get the decimal number through the database to ensure that the number is only 1, and then combine the above codes to finally generate a 10-digit non-duplicate membership card number.


Related articles: