数据压缩(2)——变长编码

2024-08-28 22:28
文章标签 编码 数据压缩

本文主要是介绍数据压缩(2)——变长编码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【定长编码】

变长和定长是很基本的概念,不光是在数据压缩,在其他很多地方都可以见到,这里就不多说了。

前文说过,在数据压缩时,我们需要用某些字符A替换或修改某些字符B,字符A占用的存储空间更小一些。

以数据集TOBEORNOT 为例,共出现T O B E R N六个字符,若是ASCII编码,需要8x9共72个二进制位。

在定长编码中,需要3个二进制(能区8种情况),即码字长度为3,需要3x9 = 27个二进制位,优化幅度很大。

描述不同的3位二进制对应什么字符的叫码字表,编码时将码字表写入,再一次写入每个字符的编码。读取时,先读取码字表,码字表和字符之前很好区分;字符之间可以通过固定长度区分。

可以发现,ASCII编码实际就是定长编码,给英文字母、数字、常见符号编码,用了8个二进制位。

你可以推测,我们一般用ASCII编码或其他文本编码方式保存的文本文件一定存在类似码字表的东西。

我们给的数据集的例子很小,实际上数据集中的字符个数(即长度)成千上万很正常。随着长度越来越长,出现的不同字符就会越来越多。

如果ASCII表上的大部分字符都出现过了,那么定长编码的压缩方式就很差,需要采用变长编码。

【变长编码】

变长编码(VLC,variable-length codes)会给出现频率高的字符更短的码字,这样编码后数据集的整体长度就降低。

其核心在于需要通过一套规则,给不同字符合适的码字,以确保频率高的字符有更短的码字,并使得不同码字可以互相区分。

难点在于如何从一个01的stream中区分码字,定长编码每次读取固定长度就行,变长编码不清楚每次需要读取的长度。

一种常见的思路是给定每次需要读取的长度。这种方式在数据压缩中行不通,因为长度的存储本身也要占用一定空间。

也即,不能通过太多额外的信息去确定,需要通过从stream本身已经读取或即将读取的二进制位做区分。

对数据集进行变长编码的步骤是:

  1. 遍历数据集中的所有字符并计算每个字符出现的频率
  2. 根据频率给不同字符分配码字,并建立码字表
  3. 再次遍历数据集根据码字表压缩数据集

VLC算法主要是关于如何生成码字的,各种各样的算法很多,需要用的时候查论文即可。但VLC不是目前主流的压缩算法,只在特定的少数场景下才会使用。

【Varint编码】

ProtoBuf中的Varint是VLC适应计算机的拓展算法,可以看到VLC的码字不按字节或字对齐,每次只读取一个二进制位,解码性能很差。

其被用来编码整数,编码时会在一个字节(=8bit)的最高位设置(MSB)为1来区分字符,如果当前读取的字节的最高位为1,那么表示需要继续读取下一位,剩下的7位用来表示该数的二进制补码。

例如,整数10可表示为 0000 1010, 整数300的二进制为1 0010 1100,补码是其自身,需要两个字节,先从低到高取7位再加上MSB为 1010 1100,另外要给编码的字节为0000 0010,合起来为300的编码1010 1100 0000 0010

正常情况下一个int类型要4个字节,而采用这种方式,对于小一些的整数,一个字节就够了,稍微大些的整数,两个字节也没问题。更大的整数会导致超出4个字节。

而在使用PB的大部分场景中,int类型整数都不会太大。

更进一步来看,所有字符都是01组合表示的,都可以当作整数来看待,都可以使用Varint编码

这篇关于数据压缩(2)——变长编码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1116061

相关文章

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

form表单提交编码的问题

浏览器在form提交后,会生成一个HTTP的头部信息"content-type",标准规定其形式为Content-type: application/x-www-form-urlencoded; charset=UTF-8        那么我们如果需要修改编码,不使用默认的,那么可以如下这样操作修改编码,来满足需求: hmtl代码:   <meta http-equiv="Conte

4-4.Andorid Camera 之简化编码模板(获取摄像头 ID、选择最优预览尺寸)

一、Camera 简化思路 在 Camera 的开发中,其实我们通常只关注打开相机、图像预览和关闭相机,其他的步骤我们不应该花费太多的精力 为此,应该提供一个工具类,它有处理相机的一些基本工具方法,包括获取摄像头 ID、选择最优预览尺寸以及打印相机参数信息 二、Camera 工具类 CameraIdResult.java public class CameraIdResult {

Python字符编码及应用

字符集概念 字符集就是一套文字符号及其编码的描述。从第一个计算机字符集ASCII开始,为了处理不同的文字,发明过几百种字符集,例如ASCII、USC、GBK、BIG5等,这些不同的字符集从收录到编码都各不相同。在编程中出现比较严重的问题是字符乱码。 几个概念 位:计算机的最小单位二进制中的一位,用二进制的0,1表示。 字节:八位组成一个字节。(位与字节有对应关系) 字符:我们肉眼可见的文字与符号。

在Eclipse环境下修改Tomcat编码的问题

问题: 由于BMS需要设置UTF-8编码,要不就会出现中文乱码问题; 一、项目保持UTF-8格式; 二、由于可能会多次移除项目、加载项目,不想每次都要修改tmp0\conf 原因: 如果在eclipse中配置了tomcat后,其实,tomcat所用的所有tomcat配置文件,都不是catalina_home/config下面的xml文件,而是在eclipse所创建的Serve

在Unity环境中使用UTF-8编码

为什么要讨论这个问题         为了避免乱码和更好的跨平台         我刚开始开发时是使用VS开发,Unity自身默认使用UTF-8 without BOM格式,但是在Unity中创建一个脚本,使用VS打开,VS自身默认使用GB2312(它应该是对应了你电脑的window版本默认选取了国标编码,或者是因为一些其他的原因)读取脚本,默认是看不到在VS中的编码格式,下面我介绍一种简单快

霍夫曼编码/译码器

赫夫曼树的应用 1、哈夫曼编码   在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用

Base64编码 及 在HTML中用Base编码直接显示图片或嵌入其他文件类型

1.为什么要用到BASE64编码的图片信息      Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一。Base64 主要不是加密,它主要的用途是把一些二进制数转成普通字符用于网络传输。由于一些二进制字符在传输协议中属于控制字符,不能直接传送需要转换一下。最常见的用途是作为电子邮件或WebService附件的传输编码.  2.base64编码定义    目前的internet