我有一个很长的数字序列,它们都低于5,我想把它编码成一个字符串,以尽可能地减少字符串长度,但保持恢复原始字符串的能力。
我想到了更高的基础:
<?php
$str = '2222342022223411112203302222232222122221230222';
$baseEncodeFrom = 5;
$baseEncodeTo = 36;
echo base_convert(base_convert($str,$baseEncodeFrom,$baseEncodeTo),$baseEncodeTo,$baseEncodeFrom);
//2222342022223411112203413300041330121304332023
但是,正如php参考文献中提到的那样,使用大数字会丢失精度,因此会丢失原始字符串。有没有办法减少原始字符串长度,仍然能够恢复原始字符串?
答案 0 :(得分:1)
您希望了解不同的压缩方法和算法,因为您可以在多大程度上压缩将取决于算法。例如,这是一个非常天真的天真和可能效率低下的算法。
<?php
$str = '2222342022223411112203302222232222122221230222';
echo $str . "\r\n";
$values = [
];
$lastChar = null;
$value = [];
foreach (str_split($str) as $character) {
if ($lastChar === null) {
$value = ['number' => $character, 'count' => 1];
$lastChar = $character;
continue;
}
if ($lastChar !== $character) {
$values[] = $value;
$value = ['number' => $character, 'count' => 0];
}
$value['count']++;
$lastChar = $character;
}
$values[] = $value;
function combine($a, $b) {
return str_pad(base_convert($a, 10, 2), 5, "0", STR_PAD_LEFT) . str_pad(base_convert($b, 10, 2), 3, "0", STR_PAD_LEFT);
}
function compressValue($value) {
$return = '';
if ($value['count'] > 8) {
$return .= compressValue(['number' => $value['number'], 'count' => $value['count'] - 8]);
$value['count'] = $value['count'] % 8;
}
$return .= combine($value['count'], $value['number']);
return $return;
};
$values = array_map('compressValue', $values);
$values = join("", $values);
$values = str_split($values, 8);
$values = array_map(function ($value) {
$ord = chr(bindec($value));
return $ord;
}, $values);
$values = join("", $values);
echo $values . "\r\n";
echo strlen($values) . "\r\n";
echo strlen($str) . "\r\n";
哪个输出......很多不可读的字符。有一个23的strlen!比原来的46短!
那它是做什么用的?它需要字符串,然后说“4”,然后是“1x3,1x4,1x2 1x0,4x2&#34;等等。然后它需要那些并将它们转换为组合二进制。我们将每个8位二进制文件设为一个字母长度。所以4x2因为00100。 010由于所有数字都低于5,我们使用二进制的最后3位数字表示数字,另外5表示数字。如果超过31(我们可以存储的最大数量为5位),我们只会将其余的存储在下一个字节中。
然后,我们有一个很长的二进制字符串,所以我们将其转换为十六进制。
所以,要转换回来,我们可以只从十六进制转换为二进制,然后将其拆分为8位数的块,并取每个块的前5个,将其转换为dec并取下块的下一个3,将其转换为dec,然后按第一个dec中的次数重复第二个dec
话虽这么说,这只是我对压缩算法的第一次尝试,而且我对它们一无所知。因此,如果您要Google了解更多信息,并研究不同的算法,您可能会发现更有效的方法。我的程序中可能还有错误,它是一个简短的概念证明
解码它的代码是
$values = str_split($values);
$values = array_map(function ($value) {
return str_pad(decbin(ord($value)), 8, "0", STR_PAD_LEFT);
}, $values);
$values = array_map(function ($value) {
$count = substr($value, 0, 5);
$number = substr($value, 5, 3);
$count = base_convert($count, 2, 10);
$number = base_convert($number, 2, 10);
return str_repeat($number, $count);
}, $values);
echo join("", $values);