首页 > 其他分享 >熵编码(四)-算术编码(二)

熵编码(四)-算术编码(二)

时间:2024-08-03 11:39:20浏览次数:7  
标签:编码 缩放 算术 High Low 寄存器 区间

目录

1. 前言

上篇文章熵编码(三)-算数编码(一)介绍了算数编码的基本流程和工作原理。本篇文章主要讲述算术编码区间缩放

2. 区间缩放背景

上篇文章编码过程使用的是无限精度的小数并且在编码结束的时候再转换成二进制。然而由于计算机能处理的精度有限,许多编码器使用的都是有限精度,从而导致编码区间随着编码会越来越小直至为0,因此可编码的字符数目受到编码器的精度限制

3. 区间缩放原理

算术编码区间范围是[0, 1)的小数,但是寄存器只能存储整数,因此寄存器存储的是区间的小数部分[0x00000000...0U, 0xFFFFFFFF....FU),区间上下限有无限个0/1.然而寄存器位数有限, 实际只能存储有限位数。
以32位寄存器为例,寄存器存储的是[0x00000000U, 0xFFFFFFFFU),但可以假象在寄存器精度之后还有无限个0/1的后缀。每当寄存器的区间下限L高位被移除时,低位补0,寄存器的区间上限H高位被移除时,低位补1。这种方式可以使用有限精度模拟无限精度。

3.1. 区间缩放基础

算术编码过程永远满足三个不等式:

  1. 区间下限Low永远单调递增
  2. 区间上限High永远单调递减
  3. 区间上限High > 区间下限Low

满足上述条件之后: 若High的最高位是0,此时Low的最高位也必定是0,那么在之后的编码过程中最高位不再变化;同理,若Low的最高位是1,此时High的最高位也必定是1,那么在之后的编码过程中最高位也不再变化。由于寄存器位数有限,为了最大化利用寄存器的位数编码,因此当区间上下限的最高位相同时,将最高位移出寄存器并输出,同时将区间上下限左移1位(通过上文可知下限补0,上限补1)。通过上述方法,我们可以充分利用寄存器的位数,也不会造成算法错误。

3.2. 区间缩放分析

上文中区间上下限最高位相同移除寄存器同时低位补0或1,属于区间缩放的两种情况。区间缩放情况分为一下三种(n是区间精度位数):

  1. 当Low最高位为1时,Low > Middle,由于High > Low永远成立,因此High的最高位也是1, 此时的小数区间是[0。5, 1),用二进制表示区间是0.1x。此时可以将High和low的最高位都移出并输出,即左移1位,同时低位补0或1:

    Low = (low - 2n-1) << 1
    High = ((High - 2n-1) << 1) | 1
  2. 当High最高位为0时,High < Middle,由于High > Low永远成立,因此Low的最高位也是0,此时的小数区间是[0, 0.5),用二进制表示区间是0.0x。此时可以将High和low的最高位都移出并输出,即左移1位,同时低位补0或1:

    Low = Low << 1
    High = (High << 1) | 1
  3. 当High最高两位是“10”,Low最高两位是“01”,此时的小数区间是[0.25, 0.75), 用二进制表示区间是0.01x或者0x10x。此时将High和Low的此高位移出,最高位不变,低位补0或1, 并且记录次高位移出次数cnt。在之后的编码过程中,遇到第一种区间缩放,输出一个0和cnt个1;遇到第二种区间缩放输出一个1和cnt个0

    Low = (low - 2n-2) << 1
    High = ((High - 2n-2) << 1) | 1

4. 区间缩放编码

以上篇文章编码示例为例,初始小数编码区间是[0, 1)。因为寄存器存储小数部分,因此寄存器编码区间是[0, 256)。下文编码过程描述的编码区间变化是寄存器编码区间变化,对应的小数编码区间变化不做描述,仅在最后输出编码结果的时候输出对应小数结果
举例:输入序列"aabbc", 符号概率如下表:

symbol a b c
probability 0.4 0.4 0.2

1.算术编码会根据概率分割初始编码区间[0,256), 其中区间的下限为表中前面的符号的累计概率

a:[0, 102), b:[102, 205), c:[205, 256)

字符序列第1个字符a,那么编码区间是[0, 102)。二进制区间[00000000b, 01100110b),区间缩放:输出一个0,最高位移出一位,缩放后二进制区间[00000000b, 11001101),编码区间是[0, 205)

2.按照字符概率重新划分[0, 205)编码区间

a:[0, 82), b:[82, 164), c:[164, 205)

字符序列第2个字符a,那么编码区间是[0, 82)。二进制区间[00000000b, 01010010b), 区间缩放:输出一个0,最高位移出一位,缩放后二进制区间[00000000b, 10100101b),编码区间是[0, 165)

3.按照字符概率重新划分[0, 165)编码区间

a:[0, 66), b:[66, 132), c:[132, 165)

字符序列第3个字符b,那么编码区间是[66, 132)。二进制区间[01000010b, 10000100b), 区间缩放:记录次高位次数cnt=1,次高位移出,缩放后二进制区间[000000100b, 10001001b),编码区间是[4, 137)

4.按照字符概率重新划分[4, 137)编码区间

a:[4, 57), b:[57, 110), c:[110, 137)

字符序列第4个字符b,那么编码区间是[57, 110)。二进制区间[00111001b, 01101110b), 区间缩放:输出一个0,次高位移出次数cnt个即一个1,最高位移出一位,缩放后二进制区间[01110010b, 11011101b),编码区间是[114, 221)

5.按照字符概率重新划分[114, 221)编码区间

a:[114, 157), b:[157, 200), c:[200, 213)

字符序列第5个字符c,那么编码区间是[200, 213)。二进制区间[11001000b, 11010101b), 区间缩放:输出两个1,一个0,最高位移出三位,缩放后二进制区间[01000000b, 10101000b),编码区间是[104, 171)

缓存二进制0001110,最终的编码二进制低位补1得到结果是00011101,表示的小数是0.00011101(0.11328125)。可以看到算数编码使用区间缩放得到的编码结果和上篇文章使用无限精度小数得到的结果是一致的。说明编码方法是符合预期的,并且仅使用了8位bit实现了算数编码。使用区间缩放的算数解码流程就不叙述了,感兴趣的同学可以自己推导

标签:编码,缩放,算术,High,Low,寄存器,区间
From: https://www.cnblogs.com/yinyouzhuang/p/18327720

相关文章

  • 字符集和字符编码(Charset & Encoding)
    编码历史字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题。因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),如......
  • shell获取敏感词接口json数据更新时重启nginx+lua环境、一个逐步删除服务器上文件夹的
    一、shell获取敏感词接口json数据如有更新重启nginx+lua环境    因为工作需要,需要写一个shell脚本获取对应接口的数据(其它管理后台控制的敏感词库)。因为当前平台是nginx+lua脚本,重装加载敏感词需要重启nginx.实现起来也很简单,第一点,需要对获取的json数据进行分析,shell......
  • 接口文档,jwt,base64编码解码
    Ⅰ接口文档【一】接口文档了解#作为后端,接口写完了--->接口给前端使用 -登录接口:username,password,code#写接口的人负责写接口文档 -如何写?-写在哪?#通常在公司中: 1使用world编写,放在公共平台上2使用MD编写3第三方平台编写:showdoc -http......
  • 金蝶云星空生产入库单找仓库仓位编码SQL脚本
    业务背景有时候开发者需要后台导出生产入库单数据,仓库仓位内码需要转成编码和名称 SQL脚本SELECTa.fid,a.FBILLNO,b.FENTRYID,b.FMATERIALID,c.FSERIALID,c.FSERIALNO,b.FSTOCKID,d.FNUMBERFSTOCKNUMBER,b.FSTOCKLOCID,T3.FNUMBERFSTOCKLOCNUMBER,T31.FNAMEFSTOCKLO......
  • 无缝融入,即刻智能[1]:MaxKB知识库问答系统,零编码嵌入第三方业务系统,定制专属智能方案,用
    无缝融入,即刻智能[1]:MaxKB知识库问答系统,零编码嵌入第三方业务系统,定制专属智能方案,用户满意度飙升1.简介MaxKB(MaxKnowledgeBase)是一款基于LLM大语言模型的开源知识库问答系统,飞致云是中国领先的开源软件公司。飞致云旗下开源产品包括1Panel开源面板、JumpServer开源......
  • 07 输入捕获和编码器接口
    前言前面介绍了定时器和输出比较,这一节主要介绍一下输入捕获测量输入频率和PWM占空比,然后介绍一下编码器接口。一、输入捕获1.什么是输入捕获当输入的引脚有指定电平跳变时,会将计数器CNT中的值保存在CCR中,这个就称为输入捕获。2.输入捕获测频率我们可以通过获取输入的值来测......
  • x264 中多线程相关编码参数详细介绍
    多线程编码相关参数参数名称参数类型参数含义cpuuint32_tcpu型号i_threadsint并行编码线程数i_lookahead_threadsint在lookahead分析中使用多线程b_deterministicint当开启多线程时是否允许非确定性优化b_sliced_threadsint是否使用基于......
  • Kotlin 运算符详解:算术、赋值、比较与逻辑运算符全解析
    Kotlin运算符运算符用于对变量和值执行操作。值称为操作数,而操作符定义了要在两个操作数之间执行的操作:操作数运算符操作数100+50在下面的示例中,数字100和50是操作数,+号是运算符:示例varx=100+50虽然+运算符通常用于将两个值相加,如上例所示,但它也可以用......
  • 从 UTF-8 编码到 GBK 编码的转换,解决中文在日志里显示乱码
    从UTF-8编码到GBK编码的转换,通过中间步骤先将UTF-8转换为宽字符,再将宽字符转换为GBK。std::stringUtf8ToGbk(conststd::string&utf8){intlen=MultiByteToWideChar(CP_UTF8,0,utf8.c_str(),-1,NULL,0);std::unique_ptr<wchar_t[]>wstr(newwchar_t......
  • 将 HTTP 分块编码数据流代码片段从 Node.js 转换为 Python
    我有一个Node.js客户端代码,它将请求发送到HTTP服务器,然后连续接收分块编码数据。这是带有一些流量数据输出的Node.js代码。consthttp=require('http');constoptions={hostname:'...',path:'...',port:...,...};constreq=http.request(......