Solved

# How to turn a large number into a shorter one with letters

Posted on 2012-09-09
574 Views
Hello,

I'm generating an order number based on the unix timestamp and a random number added to the end to make sure that it is a globally unique number.

The number ends up being really long and I would like to put some letters in it.

Is there a good way to take the generated numbers and convert it to something shorter with letters in it.  Or a better way to generate a unique identifier with letters.  I used the unix time since it makes sure that all orders have a different number.

Here is a sample number:
6134713354211947

thanks!!
0
Question by:parlays

LVL 6

Assisted Solution

Unfortunately as soon as you say turn it to the likes of say a scientific notation it fits outside the boundaries of a number and falls as a varchar.
You could try a root derivative maybe?

See below for others who have had similar issues.

0

LVL 55

Assisted Solution

You can use base-36 or base-64 encoding.
PHP has a ready-made function for base-64 called base64_encode (http://php.net/manual/en/function.base64-encode.php) but unfortunately it may produce a string larger than the original, so I suggest to use base_convert (http://php.net/manual/en/function.base-convert.php) instead for base-36 conversion:

\$returnValue = base_convert('6134713354211947', 10, 36);
// Result string is: 1oekoephqp7
0

LVL 2

Assisted Solution

you could convert the decimal to hex...?
it would give you a shorter number string containing letters.
use the dechex() and hexdec() functions to convert between the two.
0

LVL 27

Assisted Solution

do{
\$id=rand()%1000000000;
\$result=mysql_query("Select * from MyTable where id=\$id;",\$conn);
}while(mysql_num_rows(\$result)>0);

This will simply generate a random id, then check to make sure it is not in the table already.

As long as your random number size is sufficiently large, the chance of a duplicate being generated for a second order while the first order is being processed approaches zero.
0

LVL 107

Assisted Solution

Unfortunately the UNIX timestamp will not necessarily be unique.  Two orders might arrive at the same second.

You might make the md5() string of the UNIX timestamp, plus the product, plus the IP address plus your salt string.  That would almost certainly be unique.  Store this string in a VARCHAR(32) column.
http://us3.php.net/manual/en/function.md5.php

Another way to make a unique key is shown in the code snippet.

``````<?php // RAY_random_unique_string.php
error_reporting(E_ALL);
echo "<pre>";

// GENERATE A SHORT UNIQUE RANDOM STRING FOR USE AS SOME KIND OF KEY
// WE DELIBERATELY OMIT LOOK-ALIKE LETTERS LIKE O and 0, I and 1.
// NOTE THAT THE DATA BASE MUST HAVE THE rand_key FIELD DEFINED AS "UNIQUE"
// NOTE THAT THE LENGTH ARGUMENT MUST MATCH THROUGHOUT SO WE DEFINE() IT.

define('ARG_LENGTH', 6);

// CONNECTION AND SELECTION VARIABLES FOR THE DATABASE
\$db_host = "??"; // PROBABLY 'localhost' IS OK
\$db_user = "??";
\$db_word = "??";
\$db_name = "??";

// OPEN A CONNECTION TO THE DATA BASE SERVER
// MAN PAGE: http://php.net/manual/en/function.mysql-connect.php
if (!\$db_connection = mysql_connect("\$db_host", "\$db_user", "\$db_word"))
{
\$errmsg = mysql_errno() . ' ' . mysql_error();
echo "<br/>NO DB CONNECTION: ";
echo "<br/> \$errmsg <br/>";
}

// SELECT THE MYSQL DATA BASE
// MAN PAGE: http://php.net/manual/en/function.mysql-select-db.php
if (!\$db_sel = mysql_select_db(\$db_name, \$db_connection))
{
\$errmsg = mysql_errno() . ' ' . mysql_error();
echo "<br/>NO DB SELECTION: ";
echo "<br/> \$errmsg <br/>";
die('NO DATA BASE');
}
// IF WE GOT THIS FAR WE CAN DO QUERIES

// FUNCTION TO CREATE A DATABASE TABLE
function create_myTable()
{
\$length = ARG_LENGTH;

mysql_query("DROP TABLE myTable");
\$psql
=
" CREATE TEMPORARY TABLE myTable
( _key        INT(8)            NOT NULL AUTO_INCREMENT
, rand_key    VARCHAR(\$length)  UNIQUE NOT NULL DEFAULT '?'
, PRIMARY KEY(`_key`)
) ENGINE=INNODB DEFAULT CHARSET=ascii
"
;
if (!mysql_query(\$psql)) die( "FAIL: \$psql <br/>" . mysql_error() );
}

// FUNCTION TO MAKE A RANDOM STRING
function random_string()
{
//     1...5...10...15...20...25...30......
\$alphabet = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
\$string   = "";
while(strlen(\$string) < ARG_LENGTH)
{
\$string .= substr(\$alphabet, mt_rand(0,(strlen(\$alphabet))), 1);
}
return(\$string);
}

// FUNCTION TO ENSURE THE RANDOM STRING IS UNIQUE
function make_random_key()
{
\$rand_key = '';

// GENERATE A UNIQUE AND RANDOM TOKEN
while (\$rand_key == '')
{
\$rand_key = random_string(ARG_LENGTH);
\$isql     = "INSERT INTO myTable ( rand_key ) VALUES ( '\$rand_key' )";

// IF QUERY ERROR
if (!mysql_query(\$isql))
{
\$err = mysql_errno();

// DUPLICATE UNIQUE FIELD ON rand_key
if (\$err == 1062)
{
// ACTIVATE THIS TO VISUALIZE KEY COLLISIONS
// echo PHP_EOL . \$rand_key;

// NULLIFY THIS KEY AND TRY AGAIN
\$rand_key = '';
}

// OTHER QUERY ERROR
else
{
/* HANDLE FATAL QUERY ERROR (\$isql) */
}
}
}
return \$rand_key;
}

// SHOW HOW TO MAKE LOTS OF UNIQUE AND RANDOM STRINGS
create_myTable();

\$kount = 0;
\$array = array();
while (\$kount < 100)
{
\$array[] = make_random_key();
\$kount++;
}

print_r(\$array);
``````
HTH, ~Ray
0

LVL 25

Expert Comment

what about creating an auto incrementing primary key in the database to use as the order number. this will always be unique.
0

LVL 33

Accepted Solution

greetings : parlays , , Guaranteeing a Unique ID is not so easy , but there is a php function that is suppose to do that see uniqid( ) function in the manual at -
http://www.php.net/manual/en/function.uniqid.php

I have seen several that say the php function microtime( ) can give a fine enough difference to almost Guarantee a unique number, so I'll use that for a number base -

in the code below I chop off the first two characters in the microtime string, since They rarely ever change.
next I convert the numbers to Capital Letters, by simply shifting them up the ascii order 20 places, next I
add a single random character to the beginning to help it be unique, The unique ID will be in the \$mt2 string.

``````\$mt = ''.microtime(true);
\$mt = str_replace('.', '', \$mt);// remove the period
\$mt2 = substr(\$mt,2);// chop off first two
\$e = strlen(\$mt2);
for (\$i = 0; \$i <\$e; ++\$i) \$mt2{\$i} = chr(ord(\$mt2{\$i})+20);// convert numbers
echo 'UNIQUE ID',strlen(\$mt),' microtime= ',\$mt,' mt2= ',\$mt2,'<br />';
``````

Maybe you can get something from this?
0

LVL 9

Assisted Solution

You state
...and I would like to put some letters in it.

this implies that you want an alpha-numeric key, which is a string in coding and a varchar in SQL Server, or Oracle, etc.
Note: If you are going to use alpha keys in a database like SQL Server, it would be a good idea to ensure it was installed with binary collation.

How big does the number have to be? For example, how many entries will be made in, say, a year?
Would it exceed MaxInt, ie 2^31 (-2,147,483,648 to +2,147,483,647 signed, or 0 to 4,294,967,295 unsigned)?

If, I go on the assumption that you will not exceed MaxInt new entries in a given year, then it is easy to create a unique identifier.
You could stay with numbers and convert them to chars, so the number 2012345, would be stored as '2' '0' '1' '2' '3' '4' '5'

Now the numbering system would be to add two digits to the start of the number. This would be the last two digits of the year, in this case 12, then just append the three-digit Julian-Day number, and then append a unique and incrementing integer, zero-filled to however many places you need.
Thus, for September 12, 2012, for the 32nd entry, the number would be:
12+256+00000000032
The next entry would be: 12+256+00000000033
In this way, you never run out. The first two numbers for the year is good right up to 2099.
0

Author Closing Comment

thanks so much everyone!
0

LVL 33

Expert Comment

OK, glad you got something to work, After I posted here last time, I got to consider that the mt_rand( ) is seeded with a server time stamp, so It likely will not be different with the same microtime( ), and according to some, it is possible in muti-processor servers to get the same microtime( ) , , so I did this to get a unique ID, instead of any call to get a random, I get the IP from \$_SERVER['REMOTE_ADDR'], which will probally be different if the microtime( ) is identical.  AND I looked up a neat function to shorten an integer string, it's -
base_convert(\$uID, 10, 36);
you might use it to get a shorter string for integer strings.

below is the code for the makeUID(\$noNum = false)  function, which always outputs an eleven character string.
if you set the \$noNum  to true it will have NO integers in the string just a-z in lower and Caps

``````function makeUID(\$noNum = false) {
if (strlen(\$ip)<2) \$ip = '91'; else {
\$ip = str_replace('.', '', \$ip);
\$ip=substr(\$ip,strlen(\$ip)-2);
}
\$mt = microtime(false);
\$uID=substr(\$mt,2,6);
\$mt=substr(\$mt,13);
\$as4 = (int) \$ip{1};
\$as2 = (int) \$uID{5};
\$e2 = \$as2+\$as4;
\$uID=\$mt.\$ip.\$uID;
\$k2 = array('6','3','7','4','9','5','4','8','3','8','7','4','5','9','3','8','6','5','3');
\$uID{0}= \$k2[\$e2];
\$uID=base_convert(\$uID, 10, 36);
if (\$noNum) \$uID = strtr(\$uID, '01234567890', 'VBMDPFUHWR');
return \$uID;
}

\$uID = makeUID();
\$uID2 = makeUID(true);
echo strlen(\$uID),'=length, uID= ',\$uID,' , uID2= ',\$uID2,'<br />';
``````

I believe this will have a very very high probability to generate unique strings
0

Author Comment

You are the man!  I appreciate you taking the time with those write-ups, I learned a lot.  Thanks!!
0

## Featured Post

Consider the following scenario: You are working on a website and make something great - something that lets the server work with information submitted by your users. This could be anything, from a simple guestbook to a e-Money solution. But what…
This article will explain how to display the first page of your Microsoft Word documents (e.g. .doc, .docx, etc...) as images in a web page programatically. I have scoured the web on a way to do this unsuccessfully. The goal is to produce something …
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.