I've been playing about with the uniqid but it started giving me the 13 long string.
I'm looking for a prefix of 100 with up to 6 random numbers afterwards
thanks any help appreciated
function generate_order(){
$order_ref="";
$a=uniqid(prefix,100);
$num4=array('0','1','2','3','4','5','6','7','8','9');
$num=rand(0,9);
$num2=rand(0,9);
$num3=rand(0,9);
shuffle($num4);
//now the final
$order_ref = $num4[0].$num4[3].$num.$num4[1].$num2.$num4[2].$num3.$num4[4];
}
I've got some remakrs to the code above:
Why are you doing a shuffle() on an array with numbers ranging from 1 to 9? This is the same as doing rand(1,9)
Taking point one into account, using rand(10000000, 99999999) will give you the same result.
$a=uniqid(prefix,100) is not used in your function
The prefix in uniqid() should be a string.
Your function doesn't return. You should use return $order_ref;
Hope these will help you fix your function.
In response to your comment
$order_ref = '100'.rand(100000, 999999);
Additional suggestions
If you are planning to use this as an order reference as I suspect, I do not recommand just using random numbers. This will give you a big chance of having duplicate numbers.
Instead, I suggest using $order_ref = '100'.date('u').rand(10, 99);. This will give you a random number based on the current time and thus prevent (or at least minimize) the chance of duplicate order references.
If you want 100 before your result, then use the prefix to enter your desired string
Using uniqid(100) should give you the desired result.
Here is how I would do
1. Define your prefix
2. Generate random number
3. Concat both
$prefix="some_prefix";
$rand_no = rand(1,100);
$rand_no_with_prefix = $prefix.$rand_no;
You can Google for exact syntax and functions.
This is just basic logic I would follow.
Hope it helps.
Also step 4 would be to parse if required(if concated random number needs to be integer)
Related
I need to parse a json that contains a long number (that was produces in a java servlet). The problem is the long number gets rounded.
When this code is executed:
var s = '{"x":6855337641038665531}';
var obj = JSON.parse(s);
alert (obj.x);
the output is:
6855337641038666000
see an example here: http://jsfiddle.net/huqUh/
why is that, and how can I solve it?
As others have stated, this is because the number is too big. However, you can work around this limitation by sending the number as a string like so:
var s = '{"x":"6855337641038665531"}';
Then instead of using JSON.parse(), you can use a library such as javascript-bignum to work with the number.
It's too big of a number. JavaScript uses double-precision floats for numbers, and they have about 15 digits of precision (in base 10). The highest integer that JavaScript can reliably save is something like 251.
The solution is to use reasonable numbers. There is no real way to handle such large numbers.
The largest number JavaScript can handle without loss of precision is 9007199254740992.
I faced this issue some time ago, I was able to solve using this lib: https://github.com/josdejong/lossless-json
You can check this example:
let text = '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}';
// JSON.parse will lose some digits and a whole number:
console.log(JSON.stringify(JSON.parse(text)));
// '{"normal":2.3,"long":123456789012345680000,"big":null}' WHOOPS!!!
// LosslessJSON.parse will preserve big numbers:
console.log(LosslessJSON.stringify(LosslessJSON.parse(text)));
// '{"normal":2.3,"long":123456789012345678901,"big":2.3e+500}'
I want some generator script to generate unique numbers but not in one order. We need to sell tickets.
For example currently ticket numbers are like this:
100000
100001
100002
...
So the users can see how many are sold.
How can I generate unique numbers?
for example:
151647
457561
752163
...
I could use random number generator, but then I have always check in database if such number has not been generated.
Hmm, maybe when using index on that column - the check would not take long.
Still now I have to get last card number, if I want to add 1 to it, but getting last is fast enough.
And the more tickets will be sold, then bigger chance that RNG will generate existing number. So migth be more checks in future. SO the best would be to take last number and generate next by it.
Here's a simple way to scramble ticket numbers (note: you need 64-bit PHP, or change the code to use the bcmath library):
function scramble($number) {
return (305914*($number-100000)+151647) % 999983;
}
Look, the output even looks like your example:
Input Output
------ ------
100000 151647
100001 457561
100002 763475
100003 069406
If you want to you can reverse it, so you can use these codes in URLs and then recover the original number:
function unscramble($number) {
return (605673*($number-151647)+100000) % 999983 ;
}
Is this safe? Someone with access to many sequential numbers can find the pattern so don't use this if the ticket numbers are extremely sensitive.
Generate random numbers, make the ticket number unique index, insert the record with the new ticket, if fails means that you had a collision, so you have to generate another id. With a good random space, say 32 bit integer, the chance of collision is minimal. The SQL implementation behind if the column is index and numerical is lightning fast.
You can have your number generated, store in a pool, when you need new number, get one with RNG index of the pool, remove from the pool and return it.
if the pool nearly run out, just generate another batch of it
function generateCode() {
$chars = '01234567890';
do {
$code = '';
for ($x = 0; $x < 6; $x++) {
$code .= $chars[ rand(0, strlen($chars)-1) ];
}
you may check here in databse if this code has been generated earlier, if yes, return;
} while (true);
return $code;
}
The easy way, you can simply use md5() function..
And to get a 6 digit string, you can do
$x = md5(microtime());
echo substr($x, 0, 6);
Edit:
session_start();
$x = md5(microtime().session_id());
echo substr($x, 0, 6);
I have the following line of code in javascript:
(Math.random() + "") * 1000000000000000000
which generates numbers like:
350303159372528000
I tried the same thing in PHP with this:
rand()*1000000000000000000
Which returns:
2.272e+21
I need to use PHP as the number generated will be stored as a SESSION variable and will be used by JavaScript later on.
How do I get PHP to force the number to be an int rather than a float?
EDIT PHP seems to struggle with this.
Would it work if I just generated the rand number in PHP saved it to the SESSION and then done the multiplying by 1000000000000000000 in JavaScript?
How would I go about this?
I'd recommend calling
PHP_INT_MAX
To see if your PHP installation can handle an integar that large. I'm guessing it can't which is why it is knocking it down to scientific notation.
I'd suggest converting your result to an int:
intval(rand()*1000000000000000000)
That said, see Kolink and Jeremy1026 answers for precision issues. If you only need an unique identifier, see Truth's answer.
Update: if you're using strings to represent your numbers, don't want or can't use an arbitrary precision library, and don't stricly need perfecly fair random numbers, you could generate smaller numbers and concat them together:
strval(rand()*999999999 + 1) . strval(rand()*1000000000)
(The +1 is to avoid a leading zero in your result; note also that your number will never have a single digit, but every other number is possible)
For a random number with (exactly) 18 digits, you can also use str_pad in the 2nd part, to fill it with leading zeros:
strval(rand(100000000,999999999)) .
str_pad(strval(rand(0,999999999)), 9, "0", STR_PAD_LEFT)
If you need a unique identifier (which is what it looks like you're trying to do), please use PHP's uniqid() function.
floor() / ceil() / round() / (int) / intval() will convert the number to int.
Also, rand() takes two arguments. If ints are supplied - it will return an integer
And printf() should take care of printing in the format you wish (printf('%d', $int) should do the trick)
In the end I solved the issue like this:
<?php
error_reporting(0);
function RandNumber($e){
for($i=0;$i<$e;$i++){
$rand = $rand . rand(0, 9);
}
return $rand;
}
echo RandNumber(18);
// Outputs a 18 digit random number
?>
I'm interested in creating tiny url like links. My idea was to simply store an incrementing identifier for every long url posted and then convert this id to it's base 36 variant, like the following in PHP:
$tinyurl = base_convert($id, 10, 36)
The problem here is that the result is guessable, while it has to be hard to guess what the next url is going to be, while still being short (tiny). Eg. atm if my last tinyurl was a1, the next one will be a2. This is a bad thing for me.
So, how would I make sure that the resulting tiny url is not as guessable but still short?
What you are asking for is a balance between reduction of information (URLs to their indexes in your database), and artificial increase of information (to create holes in your sequence).
You have to decide how important both is for you. Another question is whether you just do not want sequential URLs to be guessable, or have them sufficiently random to make guessing any valid URL difficult.
Basically, you want to declare n out of N valid ids. Choose N smaller to make the URLs shorter, and make n smaller to generate URLs that are difficult to guess. Make n and N larger to generate more URLs when the shorter ones are taken.
To assign the ids, you can just take any kind of random generator or hash function and cap this to your target range N. If you detect a collision, choose the next random value. If you have reached a count of n unique ids, you must increase the range of your ID set (n and N).
I would simply crc32 url
$url = 'http://www.google.com';
$tinyurl = hash('crc32', $url ); // db85f073
cons: constant 8 character long identifier
This is really cheap, but if the user doesn't know it's happening then it's not as guessable, but prefix and postfix the actual id with 2 or 3 random numbers/letters.
If I saw 9d2a1me3 I wouldn't guess that dm2a2dq2 was the next in the series.
Try Xor'ing the $id with some value, e.g. $id ^ 46418 - and to convert back to your original id you just perform the same Xor again i.e. $mungedId ^ 46418. Stack this together with your base_convert and perhaps some swapping of chars in the resultant string and it'll get quite tricky to guess a URL.
Another way would be to set the maximum number of characters for the URL (let's say it's n). You could then choose a random number between 1 and n!, which would be your permutation number.
On which new URL, you would increment the id and use the permutation number to associate the actual id that would be used. Finally, you would base 32 (or whatever) encode your URL. This would be perfectly random and perfectly reversible.
If you want an injective function, you can use any form of encryption. For instance:
<?php
$key = "my secret";
$enc = mcrypt_ecb (MCRYPT_3DES, $key, "42", MCRYPT_ENCRYPT);
$f = unpack("H*", $enc);
$value = reset($f);
var_dump($value); //string(16) "1399e6a37a6e9870"
To reverse:
$rf = pack("H*", $value);
$dec = rtrim(mcrypt_ecb (MCRYPT_3DES, $key, $rf, MCRYPT_DECRYPT), "\x00");
var_dump($dec); //string(2) "42"
This will not give you a number in base 32; it will give you the encrypted data with each byte converted to base 16 (i.e., the conversion is global). If you really need, you can trivially convert this to base 10 and then to base 32 with any library that supports big integers.
You can pre-define the 4-character codes in advance (all possible combinations), then randomize that list and store it in this random order in a data table. When you want a new value, just grab the first one off the top and remove it from the list. It's fast, no on-the-fly calculation, and guarantees pseudo-randomness to the end-user.
Hashids is an open-source library that generates short, unique, non-sequential, YouTube-like ids from one or many numbers. You can think of it as an algorithm to obfuscate numbers.
It converts numbers like 347 into strings like "yr8", or array like [27, 986] into "3kTMd". You can also decode those ids back. This is useful in bundling several parameters into one or simply using them as short UIDs.
Use it when you don't want to expose your database ids to the user.
It allows custom alphabet as well as salt, so ids are unique only to you.
Incremental input is mangled to stay unguessable.
There are no collisions because the method is based on integer to hex conversion.
It was written with the intent of placing created ids in visible places, like the URL. Therefore, the algorithm avoids generating most common English curse words.
Code example
$hashids = new Hashids();
$id = $hashids->encode(1, 2, 3); // o2fXhV
$numbers = $hashids->decode($id); // [1, 2, 3]
I ended up creating a md5 sum of the identifier, use the first 4 alphanumerics of it and if this is a duplicate simply increment the length until it is no longer a duplicate.
function idToTinyurl($id) {
$md5 = md5($id);
for ($i = 4; $i < strlen($md5); $i++) {
$possibleTinyurl = substr($md5, 0, $i);
$res = mysql_query("SELECT id FROM tabke WHERE tinyurl='".$possibleTinyurl."' LIMIT 1");
if (mysql_num_rows($res) == 0) return $possibleTinyurl;
}
return $md5;
}
Accepted relet's answer as it's lead me to this strategy.
I'm have build an up php script to host large number of images upload by user, what is the best way to generate random numbers to image filenames so that in future there would be no filename conflict? Be it like Imageshack. Thanks.
$better_token = uniqid(md5(mt_rand()), true);
Easiest way would be a new GUID for each file.
http://www.php.net/manual/en/function.uniqid.php#65879
Here's how I implemented your solution
This example assumes i want to
Get a list, containing 50 numbers that is unique and random, and
This list of # to come from the number range of 0 to 1000
Code:
//developed by www.fatphuc.com
$array = array(); //define the array
//set random # range
$minNum = 0;
$maxNum = 1000;
// i just created this function, since we’ll be generating
// # in various sections, and i just want to make sure that
// if we need to change how we generate random #, we don’t
// have to make multiple changes to the codes everywhere.
// (basically, to prevent mistakes)
function GenerateRandomNumber($minNum, $maxNum){
return round(rand($minNum, $maxNum));
}
//generate 49 more random #s to give a total of 50 random #s
for($i = 1; $i <= 49; $i++){
$num1 = GenerateRandomNumber($minNum, $maxNum);
while(in_array($num1, $array)){
$num1 = GenerateRandomNumber($minNum, $maxNum);
}
$array[$i] = $num1;
}
asort($array); //just want to sort the array
//this simply prints the list of #s in list style
echo '<ol>';
foreach ($array as $var){
echo '<li>';
echo $var;
echo '</li>';
}
echo '</ol>';
Keep a persistent list of all the previous numbers you've generated(in a database table or in a file) and check that a newly generated number is not amongst the ones on the list. If you find this to be prohibitively expensive, generate random numbers on a sufficient number of bits to guarantee a very low probability of collision.
You can also use an incremental approach of assigning these numbers, like a concatenation of a timestamp_part based on the current time and a random_part, just to make sure you don't get collisions if multiple users upload files at the same time.
You could use microtime() as suggested above and then appending an hash of the original filename to further avoid collisions in the (rare) case of exact contemporary uploads.
There are several flaws in your postulate that random values will be unique - regardless of how good the random number generator is. Also, the better the random number generator, the longer it takes to calculate results.
Wouldn't it be better to use a hash of the datafile - that way you get the added benefit of detecting duplicate submissions.
If detecting duplicates is known to be a non-issue, then I'd still recommend this approach but modify the output based on detected collisions (but using a MUCH cheaper computation method than that proposed by Lo'oris) e.g.
$candidate_name=generate_hash_of_file($input_file);
$offset=0;
while ((file_exists($candidate_name . strrev($offset) && ($offset<50)) {
$offset++;
}
if ($offset<50) {
rename($input_file, $candidate_name . strrev($offset));
} else {
print "Congratulations - you've got the biggest storage network in the world by far!";
}
this would give you the capacity to store approx 25*2^63 files using a sha1 hash.
As to how to generate the hash, reading the entire file into PHP might be slow (particularly if you try to read it all into a single string to hash it). Most Linux/Posix/Unix systems come with tools like 'md5sum' which will generate a hash from a stream very efficiently.
C.
forge a filename
try to open that file
if it exists, goto 1
create the file
Using something based on a timestamp maybe. See the microtime function for details. Alternatively uniqid to generate a unique ID based on the current time.
Guaranteed unique cannot be random. Random cannot be guaranteed unique. If you want unique (without the random) then just use the integers: 0, 1, 2, ... 1235, 1236, 1237, ... Definitely unique, but not random.
If that doesn't suit, then you can have definitely unique with the appearance of random. You use encryption on the integers to make them appear random. Using DES will give you 32 bit numbers, while using AES will give you 64 bit numbers. Use either to encrypt 0, 1, 2, ... in order with the same key. All you need to store is the key and the next number to encrypt. Because encryption is reversible, then the encrypted numbers are guaranteed unique.
If 64 bit or 32 bit numbers are too large (32 bits is 8 hex digits) then look at a format preserving encryption which will give you a smaller size range at some cost in time.
My solution is usually a hash (MD5/SHA1/...) of the image contents. This has the added advantage that if people upload the same image twice you still only have one image on the hard disk, saving some space (ofc you have to make sure that the image is not deleted if one user deletes it and another user has the same image in use).