算数编码

要求:
已知三个符号的概率如下表所示, 对符号序列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);
}
posted @ 2022-01-02 20:30  kooop  阅读(296)  评论(0)    收藏  举报