算数编码
要求:
已知三个符号的概率如下表所示, 对符号序列a3 a2 a2 a1 a2 a1 a3 a2 a2 a3进行算术编码和解码。
| Letter | Probability |
|---|---|
| a1 | 0.2 |
| a2 | 0.3 |
| a3 | 0.5 |
点击查看代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
void Arithmetic(int *array, double *p) //算数编码
{
int i, j;
double l = 0, h = 1; //分别存放运算后概率区间的开始和结束位置
double next_l = 0; //中间参数
double L = 0, H = 0; //分别存放字符概率区间的开始和结束位置
double t = 1; //算数编码计算出的小数结果
int b = 0; //算数编码计算出的二进制结果
int ch[3] = {1, 2, 3}; //从零开始顺序存放字符种类
for (i = 0; i < 10; i++)
{
for (j = 0; j < 3; j++)
{
if (array[i] == ch[j])
{
L = p[j];
H = p[j + 1];
next_l = l + (h - l) * L;
h = l + (h - l) * H;
l = next_l;
}
}
}
printf("编码区间:\n[%f, %f)\n", l, h);
// t = (l + h) * 0.5;
t = h;
printf("编码结果:\n");
i = 0;
while (t > 0.0 && i < 5)
{
i++;
t = t * 2;
if (t >= 1.0)
{
printf("1");
t = t - 1;
}
else
printf("0");
}
printf("\n");
}
void Unarithmetic(double *p) //解码
{
int *array; //动态分配二进制编码数组
int b = -1; //用于接收二进制数
int i = 0, j = 0;
double t = 0;
double l = 0.2, h = 0.5; //分别存放运算后概率区间的开始和结束位置
double next_l = 0;
double next_h = 0;
int ch[3] = {1, 2, 3}; //从零开始顺序存放字符种类
printf("请输入需要解码的二进制数:\n");
array = (int *)malloc(1 * sizeof(int)); //动态分配存储空间用来存放字符串
while ((b = getchar()) != '\n') //获取字符串并统计个数
{
array = (int *)realloc(array, 1 * sizeof(int)); //再次分配存储空间用来存放字符串
array[i] = b - 48; // getchar返回的为ASCII码
i++;
}
//恢复出十进制小数
for (i = 0; i < 5; i++)
{
t += double(array[i]) * double(pow(2, (-1 - i)));
}
printf("解码结果:\n");
for (i = 0; i < 10; i++)
{
for (j = 3; j > 0; j--)
{
next_l = l;
next_h = h;
next_l += next_h * p[j - 1];
next_h *= p[j - 1];
if (t >= next_l)
{
l = next_l;
h = next_h;
printf("a%d ", j - 1);
break;
}
}
}
printf("\n");
}
int main(void)
{
int i = 0, j = 0;
int array[10] = {3, 2, 2, 1, 2, 1, 3, 2, 2, 3}; //符号序列,1表示a1,2表示a2,3表示a3
double n[3] = {0.2, 0.3, 0.5}; //符号概率
//概率区间
double p[4] = {0}; //声明一个数组用于存放概率区间
p[0] = 0;
for (i = 1; i < 4; i++) //计算概率区间
{
p[i] = p[i - 1] + n[i - 1];
}
p[4] = 1;
Arithmetic(array, p); //算数编码
Unarithmetic(p);
}

浙公网安备 33010602011771号