Modified Base 64 for URLs, or Custom/Arbitrary "Base" based on custom alphabet, in PHP
I've searched around, but after sifting through quite a lot of posts, I haven't really seen this covered --开发者_JAVA百科
I'd like to convert an unsigned, base-10 integer to a much higher "custom" base, by providing the "alphabet", but I'm not sure where to start, and am probably overlooking the simplicity.
As mentioned on wikipedia, there are variants of traditional Base 64 that do not add padding, etc., for use in URLs and what-not, but I am not sure how to begin implementing that. 8 I'm not encoding strings or binary data - just plain integer numbers - and would like to be able to feed an arbitrarily-long "alphabet" into the conversion function. Ideally, of course, I would be able to reverse the numbers as well.
I'm using PHP, but I should be able to work with anything using straightforward math and not a lot of custom libraries, of course.
On this article, you can find a function to exactly what you ask (Look at the "Creating a super-compressed URL" section) : Building a URL Shortener
Basically, that function :
- Encodes an integer,
- Allows you to use whatever alphabet you want
And there is a reverse function just below ;-)
I coded a function to do exactly this for phunction, here is the stand-alone version:
function Base($number, $input, $output, $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
{
if (strlen($charset) >= 2)
{
$input = max(2, min($input, strlen($charset)));
$output = max(2, min($output, strlen($charset)));
$number = ltrim(preg_replace('~[^' . preg_quote(substr($charset, 0, $input), '~') . ']+~', '', $number), $charset[0]);
if (strlen($number) > 0)
{
if ($input != 10)
{
$result = 0;
foreach (str_split(strrev($number)) as $key => $value)
{
$result += pow($input, $key) * intval(strpos($charset, $value));
}
$number = $result;
}
if ($output != 10)
{
$result = $charset[$number % $output];
while (($number = floor($number / $output)) > 0)
{
$result = $charset[$number % $output] . $result;
}
$number = $result;
}
return $number;
}
return $charset[0];
}
return false;
}
Here is how you can use it:
var_dump(Base(1000, 10, 62)); // g8
var_dump(Base('g8', 62, 10)); // 1000
var_dump(Base(14776336, 10, 62)); // 10000
var_dump(Base('10000', 62, 10)); // 14776336
By default I'm using a base 62 charset but you can change this to fit your needs.
精彩评论