一、实验目的
掌握算数编码原理。
二、实验内容
利用Matlab编写程序实现算数编码,包括:
1、对文件符号进行概率统计,生成编码表;
2、对文件进行压缩编码;
3、(选做)对文件进行解压缩,比较原始数据和解压后的数据之间是否有损耗。
四、实验原理
算术编码的编码对象是一则消息或一个字符序列,其编码思路是将该消息或字符序列表示成0和1之间的一个间隔(Interval)上的一个浮点小数。
在进行算术编码之前,需要对字符序列中每个字符的出现概率进行统计,根据各字符出现概率的大小,将每个字符映射到[0,1]区间上的某个子区间中。然后,再利用递归算法,将整个字符序列映射到[0,1]区间上的某个Interval中。在进行编码时,只需从该Interval中任选一个小数,将其转化为二进制数。
符号序列越长,编码表示它的Interval的间隔就越小,表示这一间隔所需的二进制位数就越多,编码输出的码字就越长。
五、实验步骤
对字符序列“state_tree”进行算术编码的步骤如下:
1、对文件符号“state_tree”进行概率统计,生成编码表;
2、初始化时,被分割范围的初始值是[0,1],即被分割范围的下限为low=0,上限为 high =1,该范围的长度为range_length=high-low =1。
第一题:
clc;
a=['_','a','e','r','s','t'];
s=input('字符串');
space=0;a1=0;e1=0;r1=0;s1=0;t1=0;
for i=1:length(s)
c=find(a==s(i));
switch c
case 1
space=space+1;
case 2
a1=a1+1;
case 3
e1=e1+1;
case 4
r1=r1+1;
case 5
s1=s1+1;
case 6
t1=t1+1;
end
end
disp('_,a,e,r,s,t概率分别是');
p=[space,a1,e1,r1,s1,t1]/length(s)
sp=cumsum(p);
low=0;high=1;range_length=high-low;
for i=1:length(s)
c=find(a==s(i));
High=sp(c);
Low=High-p(c);
next_low=low+range_length*Low;
next_high=low+range_length*High;
low=next_low;high=next_high;range_length=high-low;
disp([vpa(low,11),vpa(high,11)])
end
结果:
字符串'state_tree'
_,a,e,r,s,t概率分别是
p =
0.100000000000000 0.100000000000000 0.300000000000000 0.100000000000000 0.100000000000000 0.300000000000000
[ 0.6, 0.7]
[ 0.67, 0.7]
[ 0.673, 0.676]
[ 0.6751, 0.676]
[ 0.67528, 0.67555]
[ 0.67528, 0.675307]
[ 0.6752989, 0.675307]
[ 0.67530295, 0.67530376]
[ 0.675303112, 0.675303355]
[ 0.6753031606, 0.6753032335]
第二题:
clc;
format long
p=[0.1,0.1,0.3,0.1,0.1,0.3];
s='_aerst';
high=cumsum(p);
low=high-p;
number=input('输入数值');
while(number)
c=find((number>=low)&(number<high));
disp(s(c));
range_low=low(c);
range=p(c);
number_next=vpa(((number-range_low)/range),11);
number=double(number_next);
end
结果:
输入数值0.6753031606
s
t
a
t
e
_
t
r
e
e
感想:先设计思路,再步步分析。控制输出数字位数,vpa(a,n)输出的是syms,不能进行逻辑运算,故需要定义16位格式,将其double格式转换。而原题是11位有效数字,故后来必须vpa(a,11)将number设置,否则while循环无穷解得一堆错误字符串。