【问题标题】:Base-encoding efficiency using bases that are not powers of 2使用不是 2 的幂的碱基的碱基编码效率
【发布时间】:2017-08-29 15:37:57
【问题描述】:

Base64 将三个 8 位字符编码为四个(base-64)6 位“字符”。 Base64 是高效的,因为它使用的基数 (64) 和指数 (4) 恰好与 2 (24) 的基数为 10 的指数完美匹配:3x8=4x6=24 和 224=644=16777216.

似乎没有基数/指数组合导致值与 2 的基数 10 指数完全匹配(特别是 2n 对于任何 0n查看最后一个代码块以获取匹配指数的完整列表!

以 base92 为例,922 = 8464,最接近 2 的以 10 为底的指数为 213 = 8192。8464-8192 = 272 个索引在base92方面可用(如果我理解正确的话)是不可能利用的。 (219=524288 3=753571 20=1048576,但 220-913=295005。272 是明显的赢家。)

今天下午早些时候在思考这些损耗问题时,我想到了一个有趣的问题。如果我一次查看 14 位输入,并且遇到像 00100000 11111111 这样的输入序列,我可以将其解释为 10000011111111 或 8447,并将其编码在区域 8193n em>10000100010001, 8465,我就需要退回到使用 7 位编码。这使得这种方法对输入敏感,实际上只对起始字节为 10000100(132,ASCII 'Z')的两字节序列有用。我宁愿我的编码器不是输入敏感的。

我有两个问题:

  1. 我对 base-n 编码的理解似乎总体上是正确的吗?除了维基百科页面,我还能去哪里了解它?

  2. 对于 base32/64/128 以外的任意基数,我可以使用任何技巧或技术来提高 base-n 压缩的效率吗?

 


参考文献

回答我的问题不需要阅读以下所有内容。

这个小的 PHP 脚本计算每个可能的 base^exponent(对于 0n 的每个可能的指数sup>(对于 0n

它是为 Linux 编写的,但如果您注释掉 fprintf() 调用(其中包含一些转义序列),它应该可以在 Windows 上正常运行。

请注意,此程序将生成 30,145 行输出:)

<?php

$c = 0;
$op = 0;

for ($i = 3; $i < 513; $i++) {
    for ($j = 2; $j < 257; $j++) {
        $p = ($c * 100) / 33835;
        if ($p > $op + 5 || $p == 100) {
            fprintf(STDERR, "\rgen:  %2.1f%%", $p);
            $op = $p;
        }
        if ($i >= 2 ** 32 || $j >= 2 ** 32 || $i ** $j >= 2 ** 32) continue;
        for ($k = 1; $k < 33; $k++) {
            $x = $i ** $j - 2 ** $k;
            if ($x < 0) continue;
            if (!isset($a[$x])) $a[$x] = [];
            $a[$x][] = [ $i, $j, $k, $i ** $j, 2 ** $k, (float)sprintf("%2.1f", ((2 ** $k) / ($i ** $j)) * 100) ];
            $c++;
        }
    }
}

foreach ($a as $i => $_) {
    if ($i < 0) {
        print "\r64-bit machine required\n";
        die;
    }
}

$q = $op = $c = 0;
foreach ($a as $i => $_) {
    $p = ($c * 100) / 28013;
    if ($p > $op + 5 || $p == 100) {
        fprintf(STDERR, "\rsort: %2.1f%%", $p);
        $op = $p;
    }
    $c++;
    uasort($a[$i], function($a, $b) {
        return $a[0] < $b[0];
    });
}

fprintf(STDERR, "\rsort root\e[K");
uksort($a, function($a, $b) {
    return $a > $b;
});

fprintf(STDERR, "\r\e[K");
$l = 0;
foreach ($a as $i => $z) {
    foreach ($z as $x) {
        print
            sprintf("%5d %5.1f%%", $l++, $x[5])
            .' ('.$x[0].'^'.$x[1].'='.sprintf("%.0f", $x[0] ** $x[1]).')'
            .'-(2^'.$x[2].'='.(2 ** $x[2]).')'
            .'='.$i
            ."\n";

    }
}

如本问题开头第二段末尾所述,这里是完全匹配 2n 的指数组合的完整列表n

格式为:行号; (2^n) / (base^exponent) 以百分比表示; (base^exponent=result)-(2^exponent)=distance.

注意第 9 行的 base64。Base92 位于上述程序完整输出的第 200 行。

    0 100.0% (512^3=134217728)-(2^27=134217728)=0
    1 100.0% (512^2=262144)-(2^18=262144)=0
    2 100.0% (256^3=16777216)-(2^24=16777216)=0
    3 100.0% (256^2=65536)-(2^16=65536)=0
    4 100.0% (128^4=268435456)-(2^28=268435456)=0
    5 100.0% (128^3=2097152)-(2^21=2097152)=0
    6 100.0% (128^2=16384)-(2^14=16384)=0
    7 100.0% (64^3=262144)-(2^18=262144)=0
    8 100.0% (64^2=4096)-(2^12=4096)=0
    9 100.0% (64^4=16777216)-(2^24=16777216)=0
   10 100.0% (64^5=1073741824)-(2^30=1073741824)=0
   11 100.0% (32^6=1073741824)-(2^30=1073741824)=0
   12 100.0% (32^5=33554432)-(2^25=33554432)=0
   13 100.0% (32^4=1048576)-(2^20=1048576)=0
   14 100.0% (32^3=32768)-(2^15=32768)=0
   15 100.0% (32^2=1024)-(2^10=1024)=0
   16 100.0% (16^2=256)-(2^8=256)=0
   17 100.0% (16^7=268435456)-(2^28=268435456)=0
   18 100.0% (16^6=16777216)-(2^24=16777216)=0
   19 100.0% (16^5=1048576)-(2^20=1048576)=0
   20 100.0% (16^4=65536)-(2^16=65536)=0
   21 100.0% (16^3=4096)-(2^12=4096)=0
   22 100.0% (8^10=1073741824)-(2^30=1073741824)=0
   23 100.0% (8^8=16777216)-(2^24=16777216)=0
   24 100.0% (8^7=2097152)-(2^21=2097152)=0
   25 100.0% (8^6=262144)-(2^18=262144)=0
   26 100.0% (8^5=32768)-(2^15=32768)=0
   27 100.0% (8^4=4096)-(2^12=4096)=0
   28 100.0% (8^3=512)-(2^9=512)=0
   29 100.0% (8^2=64)-(2^6=64)=0
   30 100.0% (8^9=134217728)-(2^27=134217728)=0
   31 100.0% (4^3=64)-(2^6=64)=0
   32 100.0% (4^8=65536)-(2^16=65536)=0
   33 100.0% (4^4=256)-(2^8=256)=0
   34 100.0% (4^5=1024)-(2^10=1024)=0
   35 100.0% (4^6=4096)-(2^12=4096)=0
   36 100.0% (4^7=16384)-(2^14=16384)=0
   37 100.0% (4^13=67108864)-(2^26=67108864)=0
   38 100.0% (4^9=262144)-(2^18=262144)=0
   39 100.0% (4^10=1048576)-(2^20=1048576)=0
   40 100.0% (4^11=4194304)-(2^22=4194304)=0
   41 100.0% (4^12=16777216)-(2^24=16777216)=0
   42 100.0% (4^14=268435456)-(2^28=268435456)=0
   43 100.0% (4^15=1073741824)-(2^30=1073741824)=0
   44 100.0% (4^2=16)-(2^4=16)=0

【问题讨论】:

  • 等等,你问是否有任何k 使得k 不是2 的幂,但k^m 是2 的幂,对于某些m?不可能有这样的k。考虑素因数分解。
  • @AakashM: "...不可能有这样的k" 谢谢你 - 是的,这实际上是我想知道的(但我我还想知道是否有任何技巧/解决方法可以提高效率)。我的数学基础并不像我希望的那样实质性。 TIL 关于素数分解!

标签: algorithm bit-manipulation base


【解决方案1】:

base128 无效,因为您必须使用大于 '128' 的字符。对于字符女巫代码> = 128 chrome发送两个字节......(所以发送时这个字符的1MB字符串将更改为2MB字节......所以你失去了所有的利润)。对于 base64 字符串,这种现象不会出现(所以我们只损失了约 33%)。更多详情here in "update" section.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-03
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多