Python - b=2n 和 b!=2n 的 Golomb 编码

pythonserver side programmingprogramming更新于 2024/1/20 3:13:00

Golomb 编码是一种数据压缩技术,用于对具有特定分布的非负整数进行编码。它由 Solomon W. Golomb 于 1966 年推出,并已广泛应用于各种应用,包括视频和图像压缩、信息检索和数据存储。在本文中,我们将探索 Golomb 编码并了解两种情况,即基数是 2 的幂(b=2^n)以及基数不是 2 的幂(b ≠ 2^n)。

b=2^n 的 Golomb 编码(基数是 2 的幂)

当基数是 2 的幂时,Golomb 编码变得相对简单。让我们考虑一个 b = 4 (2^2) 的例子。

当基数是 2 的幂时,查找数字的 Golomb 编码的步骤。

确定商和余数

要对数字 (n) 进行编码,我们首先将其除以 b 并得到商 (q) 和余数 (r)。在我们的示例中,我们假设 n = 12。

n = 12

b = 4

q = n // b # 商
r = n % b # 余数

因此,在我们的示例中:

  • q = 12 // 4 = 3

  • r = 12 % 4 = 0

对商进行编码

商 (q) 使用一元编码进行编码,这意味着它由 q 个连续的 1 后跟一个 0 表示。在我们的示例中,q = 3,因此 q 的一元编码为"1110"(三个 1 后跟一个0)。

对余数进行编码

余数 (r) 使用二进制编码进行编码。由于 b = 4,我们需要使用 2 位对 r 进行编码。在我们的例子中,r = 0,可以用二进制表示为"00"。n = 12 和 b = 4 的最终 Golomb 编码是 q 的一元编码和 r 的二进制编码的串联。因此,n = 12 的 Golomb 编码为"111000"。

b ≠ 2^n(底数不是 2 的幂)的 Golomb 编码

当底数不是 2 的幂时,编码过程会变得稍微复杂一些。让我们考虑一个 b = 7 的例子。

当基数不是 2 的幂时,查找数字的哥伦布编码的步骤。

确定商和余数

与前一种情况类似,我们将数字 (n) 除以 b 得到商 (q) 和余数 (r)。假设 n = 23。

n = 23

b = 7

q = n // b # 商
r = n % b # 余数

在我们的示例中:

  • q = 23 // 7 = 3

  • r = 23 % 7 = 2

对商进行编码

与上例一样,商 (q) 使用一元编码进行编码。因此,q = 3 将以一元形式表示为 "1110"

对余数进行编码

余数 (r) 使用 Rice 编码或二进制编码进行编码。 Rice 编码通过将 r 分为前缀和后缀两部分来对其进行编码。

前缀计算

前缀通过计算 k 来确定,k 是满足 2^k ≥ b 的最小整数。在我们的示例中,b = 7,因此 k = 3。我们将范围 (R) 计算为 R = 2^k − b。在本例中,R = 2^3 − 7 = 1。如果 r < R,我们使用 k−1 位的二进制编码对 r 进行编码。否则,我们使用 k 位的二进制编码对 r+R 进行编码。在我们的示例中,r = 2 且 R = 1。由于 r < R,我们使用 k−1 = 2 位的二进制编码对 r = 2 进行编码。因此,r = 2 将用二进制表示为"10"。 n = 23 和 b = 7 的最终 Golomb 编码是 q 的一元编码和编码余数 r 的串联。因此,n = 23 的 Golomb 编码为"111010"。

Golomb 编码实现

我们可以通过创建用于一元编码、二进制编码的函数,使用 Python 实现 Golomb 编码背后的逻辑。Golomb 编码的代码实现如下所示。

示例

在下面的示例中,unary_encoding 函数对给定的商 (q) 执行一元编码。它创建一个由 q 个连续的"1"和"0"组成的字符串,以一元形式表示商。binary_encoding 函数对给定的余数 (r) 和前缀长度 (k) 执行二进制编码。如果 r 小于 2^k 和 r 之间的差,则它使用 k-1 位的二进制对 r 进行编码。否则,它使用具有 k 位的二进制对 r+2^k−r 进行编码。 golomb_encoding 函数对给定的数字 (n) 和基数 (b) 执行 Golomb 编码。它分别通过执行整数除法和模运算来计算商 (q) 和余数 (r)。以下示例涵盖的情况包括:

  • 如果基数 (b) 是 2 的幂(使用 b & (b − 1) == 0 检查),它直接将余数 (r) 转换为二进制并用零填充以匹配 b 的二进制表示的长度。

  • 如果基数 (b) 不是 2 的幂,它通过从 b 的二进制表示的长度中减去 3 来计算前缀长度 (k)。然后,它调用 binary_encoding 函数使用前缀长度 (k) 对余数 (r) 进行编码。

编码的哥伦布数是通过将一元编码商 (q) 和二进制编码余数 (r) 连接起来得到的。

def unary_encoding(q):
    """
    Perform unary encoding for the given quotient (q).
    """
    encoded = "1" * q + "0"
    return encoded


def binary_encoding(r, k):
    """
    Perform binary encoding for the given remainder (r) and prefix length (k).
    """
    if r < 2 ** k - r:
        encoded = bin(r)[2:].zfill(k - 1)
    else:
        encoded = bin(r + 2 ** k - r)[2:].zfill(k)
    return encoded


def golomb_encoding(n, b):
    """
    Perform Golomb encoding for the given number (n) and base (b).
    """
    q = n // b  # quotient
    r = n % b   # remainder

    unary_encoded = unary_encoding(q)
    if b & (b - 1) == 0:  # Check if b is a power of 2
        binary_encoded = bin(r)[2:].zfill(len(bin(b)) - 2)
    else:
        k = len(bin(b)) - 3  # Prefix length
        binary_encoded = binary_encoding(r, k)

    encoded = unary_encoded + binary_encoded
    return encoded


# 示例用法
number = 23
base = 7

encoded_number = golomb_encoding(number, base)
print("Golomb Encoding for number", number, "with base", base, ":",coded_number)

输出

Golomb Encoding for number 23 with base 7 : 1110100

结论

在本文中,我们讨论了 Golumb 编码及其相关的两种情况,即 b=2^n 和 b ≠ 2^n 。Golomb 编码是一种有用的数据压缩技术,尤其是对于具有某些模式的非负整数分布。在使用压缩算法、信息检索系统和其他数据密集型应用程序时,了解 Golomb 编码非常有用。


相关文章