【问题标题】:Turning an integer into random string and back again将整数转换为随机字符串并再次返回
【发布时间】:2011-11-15 06:03:57
【问题描述】:

我想要的是将整数转换为字符串。例如,123456789 可能会变成 8GFsah93r ......你知道像 Youtube、Pastebin 等等。然后我想把它转换回来。

我正在处理大整数,例如:131569877435989900

看看这个链接:http://codepad.viper-7.com/wHKOMi

这是我尝试使用我在网上找到的一个函数,显然......它没有正确转换回整数。我需要能够真正做到这一点的东西。

谢谢

【问题讨论】:

  • 为什么要这样做?听起来毫无意义。
  • 较短的网址...也许?
  • 这是因为您只想将整数放入较小的空间,还是将其用作安全措施?
  • 因此,将 20 位数字缩减为 10 位字符串对您有影响吗?无论哪种方式,它都不适合手动输入,并且复制/粘贴效果与 10 个字符以上一样好。
  • site.com/1234567891234567890123456789 ...必须承认,它看起来很糟糕。我不在乎你是否认为这毫无意义,事实是 - 我想这样做,我需要帮助。

标签: php


【解决方案1】:

好的,其中一个想法是使用字符数组作为数字系统的表示。然后您可以从 base 10 转换为 base 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/en/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);

如果这里有什么遗漏,请告诉我,因为它只是我图书馆里的一个 sn-p(我不想在这里插入整个东西)

黑人

【讨论】:

  • 我喜欢! codepad.viper-7.com/m7GC6U ;) 虽然我不明白... facepalm - “ulr” 有一些拼写错误,但设法修复了。
  • 当您启用 E_NOTICE 时,它确实会抛出一些未定义的偏移量......有什么办法可以解决这个问题?
  • 是的,很抱歉错别字,我从原来的内部名称重命名了这个类。 :)
  • 失败...在我的 xampp 上:131569877435989900 变成 AuIOUswE 和 AuIOUswE 变成 34227335412637 ... ?
  • 这是网址:213.249.184.108/urlshort.php 它运行的代码几乎与 viper-7 链接上的代码相同... -.-
【解决方案2】:

检查base64编码:http://php.net/manual/en/function.base64-encode.phphttp://php.net/manual/en/function.base64-decode.php

如果您想要一个较短的字符串,首先将其编码为 8 位字符串,然后再编码。您可以使用 % 256/ 256 来做到这一点。

或者您可以手动执行 base64 的操作,获取前 6 位并将其编码为字符。

【讨论】:

  • 网址会太长。另外,它们确实有特殊字符,例如:= ...我不想要它们。
  • 我会用...替换它。用 = 替换任何内容会很棘手
  • 另外:codepad.viper-7.com/MdEjia 转换成 8 位的效果不太好。
  • 大声笑,你必须反复这样做才能构建一个 8 位字符串。 php.net/manual/en/function.chr.php
【解决方案3】:

为什么不使用这样的东西?您需要对其进行高度加密吗?

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

【讨论】:

    【解决方案4】:

    我认为您想要的是使用 Base32 对 id 进行编码。生成的字符串仅包含 26 个字母和数字 2-7,使其非常易于阅读。

    【讨论】:

      【解决方案5】:

      最简单的方法是使用base_convert 之类的东西——不幸的是,它不能正确处理如此大的整数。

      但是,您可以通过从我的回答 here 复制 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);
      

      See it in action.

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

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

      添加您认为可接受的任何其他“数字”(例如,大写字母或您不介意在 URL 中包含的其他符号)。然后,您可以将上面示例中的基本36 替换为更大的(您可以达到定义的数字的任意高),它会按照您的意愿工作。

      See it here working with 62 digits.

      【讨论】:

        【解决方案6】:

        我很惊讶没有人提到 base64_encode() 和它的合作伙伴 base64_decode()。
        如果您不考虑长度,这是完美的

        $before = base64_encode(131569877435989900);
        
        $after = 'MS4zMTU2OTg3NzQzNTk5RSsxNw==';
        
        $on_reverse = base64_decode('MS4zMTU2OTg3NzQzNTk5RSsxNw==');
        $on_reverse == 131569877435989900;
        

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

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

          • 从 MD5 字符串中取出前 12 个十六进制字符通常是个坏主意,因为这样会大大增加发生冲突的机会。
          • 这只是一个示例,展示了制作“youtube”类型哈希字符串的最快方法。
          猜你喜欢
          • 2015-01-19
          • 2013-02-18
          • 2011-01-13
          • 1970-01-01
          • 2011-10-30
          • 1970-01-01
          • 2012-11-01
          • 1970-01-01
          • 2010-11-28
          相关资源
          最近更新 更多