Base10 到 Base64 网址缩短
我正在为一个正在学习 php 的项目编写一个 url 缩短函数,这里是代码(顺便说一句,我认为这里的 global
不是一件好事:P):
$alphabet = array(1 => "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"0","1","2","3","4","5","6","7","8","9","_","-");
function shorten($id){
global $alphabet;
$shortenedId = "";
while($id>0){
$remainder = $id % 64;
$id = $id / 64;
$shortenedId = $alphabet[$remainder].$shortenedId;
}
return $shortenedId;
}
代码取自这篇维基百科文章并改编为 php。我的问题是,当我将 64 的倍数传递给函数时,我得到错误的(出于我的目的)结果,例如 128 返回 b,这是不正确的,它应该是 aaa,但这对于 3 位数字来说太长了数字。
另外,我开始认为这段代码有问题,如果我将 1'000'000'000'000 作为 $id
传递,我会得到 nItOq...我觉得这是错误的,因为 url像 bit.ly 这样的缩短服务,如果我使用它,会返回一个 6 数字 id,而且我不认为这个算法比他们的更好。
那么,有两个问题:
- 您发现上述代码中存在任何错误吗?
- 如何管理64位多个ID?我是否必须忽略它们并转到下一个?
I'm coding an url shortener function for a project in which I'm learning php, here is the code (btw I suppose that global
here is not a good thing to do :P):
$alphabet = array(1 => "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
"0","1","2","3","4","5","6","7","8","9","_","-");
function shorten($id){
global $alphabet;
$shortenedId = "";
while($id>0){
$remainder = $id % 64;
$id = $id / 64;
$shortenedId = $alphabet[$remainder].$shortenedId;
}
return $shortenedId;
}
The code is taken from this Wikipedia article and adapted to php. My problem is that when I pass a multiple of 64 to the function I get a wrong (for my purpose) result, for instance 128 returns b which is not correct, it should have been aaa, but that's too long for a 3-digit number.
Also I'm starting to think that there's something wrong in this code, if I pass 1'000'000'000'000 as $id
I get nItOq... I feel it's wrong because a url shortening service like bit.ly returns a 6 number id if I use it, and I don't think that this algorithm is better than theirs.
So, two questions:
- do you spot any bug in the above code?
- how to manage 64-multiple ids? Do I have to just ignore them and pass to the next one?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
只需要一些小调整,主要的两个是使字母表零索引而不是一索引,并在除法之前从 id 中减去余数
,这是一个进一步修改的版本......好吧,我只是喜欢
< strong>编辑:排序串联与OP相同
Just a couple of little tweaks needed, the main two were to make the the alphabet zero indexed rather than one-indexed, and to subtract the remainder from the id before dividing
and here's a further modified version which... well I just like
EDIT: sorted concatenation to be the same as the OPs
如果您正在寻找相反的函数来获取 base64 数字并转换为 base10,这里有一些基于 JavaScript 的 PHP 答案:如何在PHP中将base64转换为base10?
In case you're looking for the opposite function to take a base64 number and convert to base10, here's some PHP based off of the JavaScript in this answer: How to convert base64 to base10 in PHP?
这个怎么样:
How about this:
顺便说一句,查看一下 base_convert() 函数 (http://php. net/manual/en/function.base-convert.php):
36 是它可以转换的最长基数。但在评论区我发现了这一点:
也许会有帮助?
By the way, check out the base_convert() function (http://php.net/manual/en/function.base-convert.php):
36 is the longest base it can convert to, though. But in the comments section I found this:
Maybe it will help?
Paul Greg 创建了一些从 Base-10 转换为另一个进制的 PHP 代码。可以对此进行测试并在此处下载代码:
http://www.pgregg.com /projects/php/base_conversion/base_conversion.php
我正在使用这种方法将数据库行 id 转换为 Base-64。一旦这些数字被缩短,它们就可以在 URL 中使用。[详情]
Paul Greg created some PHP code that converts from Base-10 to another base. This can be tested and the code downloaded here:
http://www.pgregg.com/projects/php/base_conversion/base_conversion.php
I'm using this approach to convert the database row id's to Base-64. Once these numbers have been shortened they can be used in the URL. [details]
这两个函数非常方便,感谢@malhal:
These two functions are very convenient, thanks to @malhal:
这是 Nathans 代码的变体,用于处理大于 PHP_INT_MAX 的大整数。
这使用了 Windows 上内置的 BC 数学函数服务器,但这需要作为 Unix 服务器上的可选扩展启用。此解决方案还需要几个自定义 BC 函数来处理我从 阿利克斯·阿克塞尔的帖子。
在 Windows(32 位)上运行 PHP 5.6 的示例
输出
如果 ID 是公共的,请避免在字符串中使用元音(例如,115617 缩写为 sex)。这将是应该提供安全词的 Base 54 版本。
This is a variation of Nathans code to handle large integers greater than PHP_INT_MAX.
This uses the BC Maths Functions that should be built-in on Windows servers, but this needs to be enabled as an optional extension on Unix servers. This solution also requires a couple of custom BC functions to handle floor and round functions that I copied from the post by Alix Axel.
Examples running PHP 5.6 on Windows (32 bit)
Outputs
If the ID is public, avoid using vowels in the string (115617 is shortened to sex for example). This would be the base 54 version that should provide safe words.
您可以使用
包
。它将产生
D62P0WqzFCo=
,它是正确的,因为$int
是 int64 并且使用 64 位。 Base64 每个字符使用 6 位,因此需要约 11 个字符。解码使用:
它将返回
1129717211140920362
。 ;)它基于葡萄牙语 Stackoverflow 的答案。
You can use the
pack
.It will result in
D62P0WqzFCo=
, it is correct, because the$int
is an int64 and uses 64 bits. The Base64 uses 6 bits for each character, so they need ~11 characters.To decode use:
It will return
1129717211140920362
. ;)It was based in the answer on the Stackoverflow in Portuguese.