6

what I'm wanting is to convert an integer into a string. For example, 123456789 may become 8GFsah93r ... you know like Youtube, Pastebin and what not. I then want to convert it back.

I'm working with large integers, for example: 131569877435989900

Take a look at this link: http://codepad.viper-7.com/wHKOMi

This is my attempt using a function I found on the web, obviously... it's not correctly converting back to integer. I'm needing something that does this realiably.

Thanks

Jeanie Tallis
  • 595
  • 2
  • 6
  • 12
  • Why do you want to do this? It sounds pointless. – Jon Sep 12 '11 at 10:59
  • Shorter urls... perhaps? – Jeanie Tallis Sep 12 '11 at 11:01
  • 1
    Is this because you just want to fit the integer into a smaller space, or are you using this as a security measure? – JJJ Sep 12 '11 at 11:01
  • 1
    So cutting down a, say, 20-digit number to a 10-digit string makes a difference for you? It's not going to be hand-type-friendly either way, and copy/paste works just as good with 10 chars more. – Jon Sep 12 '11 at 11:02
  • 1
    site.com/1234567891234567890123456789 ... gotta admit, it looks pretty awful. I don't care if you think it's pointless, fact is - I want to do it and I need help with it. – Jeanie Tallis Sep 12 '11 at 11:07
  • Base36 (A-Z0-9) is the common way used by shorteners; 131569877435989900 -> zzhmn9ztjm8 – Alex K. Sep 12 '11 at 11:13
  • OK, it's your app, you call the shots. I 've added an answer that you will hopefully find adequate. – Jon Sep 12 '11 at 11:51

7 Answers7

4

Ok, one of the ideas is to use a character array as a representation of a numeric system. Then you can convert from base 10 to base x and vica-versa. The value will be shorter and less readable (altought, you should encrypt it with a two-way crypter if it must be secure).

A solution:

final class UrlShortener {

    private static $charfeed = Array(
    'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
    'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
    'z','Z','0','1','2','3','4','5','6','7','8','9');

    public static function intToShort($number) {
        $need = count(self::$charfeed);
        $s = '';

        do {
            $s .= self::$charfeed[$number%$need];
            $number = floor($number/$need);
        } while($number > 0);

        return $s;
    }

    public static function shortToInt($string) {
        $num = 0;
        $need = count(self::$charfeed);
        $length = strlen($string);

        for($x = 0; $x < $length; $x++) {
            $key = array_search($string[$x], self::$charfeed);
            $value = $key * pow($need, $x);
            $num += $value;
        }

        return $num;
    }
}

Then you can use:

UrlShortener::intToShort(2);
UrlShortener::shortToInt("b"); 

EDIT

with large numbers, it does not work. You should use this version (with bcmath http://www.php.net/manual/en/book.bc.php ) with very large numbers:

final class UrlShortener {

    private static $charfeed = Array(
    'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
    'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
    'z','Z','0','1','2','3','4','5','6','7','8','9');

    public static function intToShort($number) {
        $need = count(self::$charfeed);
        $s = '';

        do {
            $s .= self::$charfeed[bcmod($number, $need)];
            $number = floor($number/$need);
        } while($number > 0);

        return $s;
    }

    public static function shortToInt($string) {
        $num = 0;
        $need = count(self::$charfeed);
        $length = strlen($string);

        for($x = 0; $x < $length; $x++) {
            $key = array_search($string[$x], self::$charfeed);
            $value = $key * bcpow($need, $x);
            $num += $value;
        }

        return $num;
    }
}
$original = 131569877435989900;
$short = UrlShortener::intToShort($original);
echo $short;
echo '<br/>';
$result = UrlShortener::shortToInt($short);
echo $result;
echo '<br/>';
echo bccomp($original, $result);

If something missing from here, please let me know, because it's only a snippet from my library (I don't wanna insert the whole thing here)

negra

Peter Porfy
  • 8,921
  • 3
  • 31
  • 41
2

check base64 encoding: http://php.net/manual/en/function.base64-encode.php http://php.net/manual/en/function.base64-decode.php

If you want a shorter string first encode it into an 8bit string then encode. You can do this with % 256 and / 256.

Or you could manually do what base64 does, get the first 6bits and encode it to a char.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
1

The simplest would be to use something like base_convert -- unfortunately, it won't work for such large integers correctly.

However, you can use the same idea by copying base_convert_arbitrary from my answer here and doing:

$id = '131569877435989900';
$encoded = base_convert_arbitrary($id, 10, 36);
$decoded = base_convert_arbitrary($encoded, 36, 10);

print_r($encoded);
print_r($decoded);

See it in action.

The nice thing about this approach is that you can tweak the first line inside the function, which reads:

$digits = '0123456789abcdefghijklmnopqrstuvwxyz'; // 36 "digits"

Add any other "digits" you find acceptable (e.g. capital letters or other symbols you don't mind having in your URL). You can then replace the base 36 in the above example with a larger one (you can go as high as there are defined digits), and it will work just like you want it to.

See it here working with 62 digits.

Community
  • 1
  • 1
Jon
  • 428,835
  • 81
  • 738
  • 806
0

I am suprised No one is mentioning base64_encode() and it partner base64_decode().
If you were not considering length this is perfect

$before = base64_encode(131569877435989900);

$after = 'MS4zMTU2OTg3NzQzNTk5RSsxNw==';

$on_reverse = base64_decode('MS4zMTU2OTg3NzQzNTk5RSsxNw==');
$on_reverse == 131569877435989900;

I always go for the simplest solutions, as long as they don't compromise my security.

bummi
  • 27,123
  • 14
  • 62
  • 101
lule75
  • 1
0

Why not use something like this? Do you need it heavily encrypted?

$num = 131569877435989900;
echo $str = base64_encode($num);
echo base64_decode($str);
Johnatan
  • 1,268
  • 8
  • 16
0

I think what you want is to encode the ids using Base32. The resulting string contains only the 26 letters of the alphabet and the digits 2-7, making it very human readable.

Edward Dale
  • 29,597
  • 13
  • 90
  • 129
-1

The easiest way to get random string is to use hash functions like md5() or sha1() For example:

<?php
$bigInt = '131569877435989900';
$hash = md5($bigInt);
$hashed=substr($hash,0,-20);
echo $hashed;
?>

These hash functions are irreversible-you can't get the original value(these functions are also used to crypt data). If you want you can save the original big integer in an array or a database. But decripting the hash would be impossible.

George
  • 2,050
  • 6
  • 26
  • 36
  • Getting the first 12 hexadecimal characters off an MD5 string is generally a bad idea, since you hugely increase the chances of collisions. – CodeCaster Sep 12 '11 at 11:06
  • It was just an example to show the fastest way of making 'youtube' type hash strings. – George Sep 12 '11 at 11:09