有人可以命名一个用于压缩数字的现有算法吗?数字是整数,完全随机,没有空格和小数,例如。 35637462736423478235687479567456 ....Ñ
好吧,到目前为止,我只有这个,它将整数转换为ascii,减少了原始大小的40%function intergerToChar($v)
{
$buffer="";
$charsLen=strlen($v);
for($i = 0; $i <= $charsLen; $i++)
{
$asc=$v[$i];
if($asc==0){$buffer[]=0;}
elseif($asc==1){$buffer[]=$v[$i].$v[$i+1].$v[$i+2];$i=$i+2;}
elseif($asc==2)
{
if($v[$i+1]<5){$buffer[]=$v[$i].$v[$i+1].$v[$i+2];$i=$i+2;}
elseif($v[$i+1]==5 && $v[$i+2]<6){$buffer[]=$v[$i].$v[$i+1].$v[$i+2];$i=$i+2;}
else{$buffer[]=$v[$i].$v[$i+1];$i++;}
}
else{$buffer[]=$v[$i].$v[$i+1];$i++;}
}
return $buffer;
}
不过,我知道PHP不适用于构建压缩工具。我将使用C / C ++
UPDATE :这是另一个PHP代码,压缩效果比上面的代码好,如果第1,第6,第12位的整数,它可以压缩高达66% ,th等具有小于256的值,并且跟随它们的3个整数的值不超过前面3个整数的值,1
34 2
98 1
56 2
86 1
59 ....可以压缩到66%,我认为它不是最优的,请随时提出建议/更正
function intergerToChar2($v)
{
$buffer="";
$charsLen=strlen($v);
for($i = 0; $i <= $charsLen; $i++)
{
if($v[$i].$v[$i+1].$v[$i+2]<256){$base=$v[$i].$v[$i+1].$v[$i+2];$i=$i+2;}
else{$base=$v[$i].$v[$i+1];$i=$i+1;}$i=$i+1;
if($v[$i].$v[$i+1].$v[$i+2]<256){$next=$v[$i].$v[$i+1].$v[$i+2];$i=$i+2;}
else{$next=$v[$i].$v[$i+1];$i=$i+1;}
if($next!=="")
{
$next=$next-$base;
if($next<0)$next=255+$next;
}
$buffer[]=$base;
$buffer[]=$next;
}
return $buffer;
}
btw,10位编码或40位编码可以使用base_convert()或来自http://php.net/manual/en/ref.bc.php页面的第4个注释轻松完成,该注释总是显示约58.6%的压缩率。
答案 0 :(得分:4)
如果数字是随机的,那么你不能压缩序列超过信息理论极限,即log 2 10 bits / digit。 (实际上,除非字符串的精确长度是固定的,否则它会略多于此。)您可以通过将数字表示为(非常长的)二进制数来实现该限制;然而,这是压缩和解压缩的尴尬和耗时。
非常接近最优的解决方案是因为1000仅略小于2 10 ,因此您可以使用10位表示3位数。这是3.33位/位,与理论上最佳的3.32位/位相比。 (换句话说,它是最佳的99.7%。)
由于实际上有1024个可能的10位代码,并且你只需要1000个代表3位数字,你就剩下一些了;如有必要,其中一个可用于指示流的结束。
输出10位数字有点烦人。输出40位数字更容易,因为40位正好是5个字节。幸运的是,现在大多数语言都支持40位算术(实际上是64位算术)。
(注意:这与您的解决方案没有什么不同。但它更容易一点,也更有点压缩。)