有没有一种通用的方法来编码和解码任意数据,以便编码的最终结果仅由数字组成-像base64_encode一样但没有字母?
虚构的例子:
$encoded = numbers_encode("Mary had a little lamb"); echo $encoded; // outputs e.g. 12238433742239423742322 (fictitious result) $decoded = numbers_decode("12238433742239423742322"); echo $decoded; // outputs "Mary had a little lamb"
您可以将(单字节字符)字符串视为以256为基数的编码数字,其中“ \ x00”表示0,’‘(空格,即“ \ x20”)表示32,依此类推,直到“ \ xFF”为止,代表255。
仅用数字0-9表示就可以简单地通过将表示更改为10为基数来完成。
请注意,“ base64编码”实际上不是基本转换。base64将输入分为3个字节(24位)的组,并分别对这些组进行基数转换。这很有效,因为24位数字可以用基数64(2 ^ 24 = 64 ^ 4)的四个数字表示。
这差不多是el.pescado)所做的–他将输入数据分割为8位,然后将数字转换为基数为10。但是,相对于基数为64的编码,此技术有一个缺点–它不能与基数64正确对齐。字节边界。为了表示8位数字(无符号时为0-255),我们需要以10为基数的三位数字。但是,最左边的数字比其他数字少信息。它可以是0、1或2(对于无符号数字)。
以10为底的数字存储log(10)/ log(2)位。无论您选择的块大小如何,都永远无法将表示形式与8位字节对齐(就我在上一段中所描述的“对齐”而言)。因此,最紧凑的表示形式是基本转换(您可以将其视为只有一个大块的“基本编码”)。
这是bcmath的示例。
bcscale(0); function base256ToBase10(string $string) { //argument is little-endian $result = "0"; for ($i = strlen($string)-1; $i >= 0; $i--) { $result = bcadd($result, bcmul(ord($string[$i]), bcpow(256, $i))); } return $result; } function base10ToBase256(string $number) { $result = ""; $n = $number; do { $remainder = bcmod($n, 256); $n = bcdiv($n, 256); $result .= chr($remainder); } while ($n > 0); return $result; }
对于
$string = "Mary had a little lamb"; $base10 = base256ToBase10($string); echo $base10,"\n"; $base256 = base10ToBase256($base10); echo $base256;
我们得到
36826012939234118013885831603834892771924668323094861 玛丽有只小羊羔
由于每个数字仅编码log(10)/log(2)=~3.32193位,因此期望该数字趋向于长140%(而不是长200%,这与el.pescado的答案一样)。
log(10)/log(2)=~3.32193