2011-03-24 99 views
3

我有一個6位數字和一個31位數字(例如「234536」&「201103231043330478311223582826」),我需要使用PHP在API中填入相同的22個字符的字母數字字段。我試圖將每個轉換爲基數32(必須使用自定義函數,因爲base_convert()不能很好地處理大數字)並加入一個單字符分隔符,但只能將其降至26個字符。它是一個REST API,因此這些字符需要是URI安全的。如何將6 + 31數字字符塞入22個字母數字字符?

我真的很喜歡做這個,如果可能的話,不創建數據庫表交叉引用這兩個數字與另一個參考值。有什麼建議麼?

+0

這是真的16位數的秒級? – zneak 2011-03-24 18:39:24

+2

如果我的數學是正確的,你需要使用base-54編碼。區分大小寫的字母數字編碼(base-62)應該足夠了。有沒有理由爲什麼這不起作用?你需要看代碼嗎? – Seth 2011-03-24 18:44:06

回答

3

改爲使用62的基數。這將使你得到前者3.35個字符和後者17.3個字符,總共22個字符。

>>> math.log(10**6)/math.log(62) 
3.3474826039165504 
>>> math.log(10**31)/math.log(62) 
17.295326786902177 
+0

這是否考慮到分隔這兩個數字所需的額外字符? – zneak 2011-03-24 18:44:55

+3

如果結果值爲0填充,則不需要分隔符;切割字符串就足夠了。 – 2011-03-24 18:45:51

+0

非常好!我不明白數學到達那裏,但現在我知道了!因此,像'str_pad($ base62Encoded,4,'0',STR_PAD_LEFT)'和'str_pad($ base62Encoded,18,'0',STR_PAD_LEFT)'連接在一起的東西應該填充正確,對吧? – morgant 2011-03-24 19:07:42

1

你可以寫一些類似pack(),使用bc工作與大數字。這是我的快速解決方案,它用13個字符的字符串轉換你的第二個數字。很不錯 !

<?php 
$i2 = "201103231043330478311223582826"; 

function pack_large($i) { 
    $ret = ''; 
    while(bccomp($i, 0) !== 0) { 
     $mod = bcmod($i, 256); 
     $i = bcsub($i, $mod); 
     $ret .= chr($mod); 
     $i = bcdiv($i, 256); 
    } 

    return $ret; 
} 

function unpack_large($s) { 
    $ret = '0'; 

    $len = strlen($s); 
    for($i = $len - 1; $i >= 0; --$i) { 
     $add = ord($s[$i]); 
     $ret = bcmul($ret, 256); 
     $ret = bcadd($ret, $add); 
    } 

    return $ret; 
} 

var_dump($i2); 
var_dump($pack = pack_large($i2)); 
var_dump(unpack_large($pack)); 

輸出示例:

string(30) "201103231043330478311223582826" 
string(13) "jàÙl¹9±̉" 
string(47) "201103231043330478311223582826.0000000000000000" 

由於需要URL友好字符,在包裝的字符串中使用base64_encode,這會給你一個20個字符的字符串(18,如果你刪除了填充)。

相關問題