将整数转换为随机字符串并再次转换为整数

6
我想要的是将整数转换为字符串。例如,123456789 可以变成8GFsah93r之类的字符串…就像YouTube、Pastebin等网站一样。然后我想把它转换回去。
我正在处理大整数,例如:131569877435989900
看看这个链接:http://codepad.viper-7.com/wHKOMi 这是我使用在网上找到的函数进行尝试,但明显地……它没有正确地转换回整数。我需要一个可靠的方法。谢谢。

你为什么想要这样做?听起来毫无意义。 - Jon
更短的URL...也许? - Jeanie Tallis
1
这是因为你只想将整数适应更小的空间,还是你将其用作安全措施? - JJJ
1
那么,将一个20位数缩减为10位字符串对您有影响吗?无论如何,它都不会方便手动输入,而复制/粘贴在多10个字符的情况下同样有效。 - Jon
1
网站.com/1234567891234567890123456789...得承认,它看起来非常糟糕。我不在乎你是否认为这是无意义的事情,事实是-我想做这件事,并且需要帮助。 - Jeanie Tallis
显示剩余2条评论
7个回答

4

好的,其中一个想法是使用字符数组作为数字系统的表示。然后您可以从十进制转换为基数x,反之亦然。该值将更短,但不易读(尽管如果必须安全,则应使用双向加密器进行加密)。

一种解决方案:

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;
    }
}

然后,您可以使用:

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

编辑

对于大量的数字,原版本无法正常工作。您应该使用这个版本(带有 bcmath http://www.php.net/manual/zh/book.bc.php )处理非常大的数字:

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);

如果这里有什么遗漏,请告诉我,因为这只是我的库中的一小部分(我不想在这里插入整个内容)。
黑色

我喜欢它!http://codepad.viper-7.com/m7GC6U ;) 尽管我不太理解... 扶额 - "ulr" 有几个打字错误,但已经修复。 - Jeanie Tallis
抱歉,打错了字,我将类从原始内部名称更名了。 :) - Peter Porfy
这是网址:http://213.249.184.108/urlshort.php 它基本上运行与viper-7链接上相同的代码... -.- - Jeanie Tallis
这些数字似乎太大了,无法进行此类操作...这就是为什么出现e_notice和131 569 877 435 989 900的无效转换的原因。 - Peter Porfy
@Jeanie使用BCMath版本(用于大数字)编辑了我的答案,并进行了测试。看起来可以正常工作,请检查一下。 - Peter Porfy
显示剩余3条评论

2
检查Base64编码:http://php.net/manual/en/function.base64-encode.php http://php.net/manual/en/function.base64-decode.php 如果您想要一个更短的字符串,首先将其编码为8位字符串,然后再进行编码。您可以使用% 256/ 256来完成此操作。
或者,您可以手动执行Base64所做的操作,获取前6位并将其编码为字符。

URL太长了,而且它们有特殊字符,例如:= ... 我不需要它们。 - Jeanie Tallis
我会用...什么都不替换它。用a替换什么都没有可能会很棘手。 - Jeanie Tallis
另外:http://codepad.viper-7.com/MdEjia 转换成8位并不是很顺利。 - Jeanie Tallis
哈哈,你必须重复这样做才能构建一个8位字符串。http://php.net/manual/en/function.chr.php - Karoly Horvath

1

最简单的方法是使用类似 base_convert这样的东西,但遗憾的是它不能正确地处理如此大的整数。

不过,你可以通过复制我的答案 这里中的base_convert_arbitrary并执行以下操作来使用相同的思路:

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

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

看它如何运作

这种方法的好处是你可以调整函数内的第一行,它的内容是:

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

添加任何其他您认为可接受的“数字”(例如大写字母或其他符号,您不介意在URL中拥有)。然后,您可以将上面示例中的基数36替换为更大的数字(您可以尽可能高地定义数字),它将按照您想要的方式正常工作。

在此处查看使用62个数字的演示


0
我很惊讶没有人提到base64_encode()和它的伴侣base64_decode()。
如果你不考虑长度的话,这是完美的。
$before = base64_encode(131569877435989900);

$after = 'MS4zMTU2OTg3NzQzNTk5RSsxNw==';

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

我总是选择最简单的解决方案,只要它们不影响我的安全。


0

为什么不用像这样的东西呢?你需要它加密得很严吗?

$num = 131569877435989900;
echo $str = base64_encode($num);
echo base64_decode($str);

0

我认为你想要的是使用Base32编码ids。生成的字符串仅包含字母表中的26个字母和数字2-7,使其非常易读。


-1

获取随机字符串的最简单方法是使用哈希函数,如md5()sha1()。例如:

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

这些哈希函数是不可逆的 - 你不能得到原始值(这些函数也用于加密数据)。如果你想要,你可以将原始大整数保存在数组或数据库中。但解密哈希将是不可能的。


从MD5字符串中获取前12个十六进制字符通常是一个不好的想法,因为这会极大地增加碰撞的可能性。 - CodeCaster
这只是一个例子,展示了生成“ YouTube”类型哈希字符串的最快方法。 - George

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接