数据处理方法-算术编码(香农算法、java编码实现)

一、算术编码起源

早在1948年,香农就提出将信源符号依美出现的概率降序排序,用符号序列累计概率的二进值作为对信源的编码,并从理论上论证了它的优越性。1960年,Peter Elias 发现无需排序,只要编、解码端使用相同的符号顺序即可,提出了算术编码的概念。Elias 没有公布他的发现,因为他知道算术编码在数学上虽然成立,但不可能在实际中实现。1976年,R. Pasco和] Rissanen分别用定长的寄存器实现了有限精度的算术编码。1979年Rssnen和G. G Langdon一起将算术编码系统化,并于1981年实现了二进制编码。1987 年Witten等人发表了一个实用的算术编码程序.即CACM87(后用于ITU_T的H.263视频压缩标准)。同期,IBM公司发表了著名的Q编码器(后用于JPEG和JBIG图像压缩标准)。从此,算术编码迅速得到了广泛的注意。

二、算术编码过程

算术编码的基本原理是将编码的消息表示成实数0和1之间的一个同隔(Interval), 消息越长,编码表示它的间隔就越小,表示这一间隔所需的二进制位就越多。
编码步骤:

1.根据二维码中提取的有效文本信息,计算各个信号源出现的频率,将[0, 1)这个区间分成若干段,这样每个信号源就会有自己对应的区间了;

2.将[0.1)这个区间设置为初始间隔;

3.从RFID中提取出来有效信号,共有6组,每组信号长度不等;

4.将待处理的信号,一个一个信号源的读入,每读入一个信号,就将该信号源在[0.1)上的范围等比例的缩小到最新得到的间隔中。

5.然后依次迭代,不断重复进行步骤4,直到该组中信号源全部被读完为止;

6.若通过步骤5计算得到的该组信号的概率区间记为: [n1,n2),则该组信号对应的红外报警器码计算方式为:(n1+n2)*10^x/2)%256 (其中x为各组总的迭代次数,x取值范围1-5)

7.重复步骤4、5、6将6组信号全部处理完成,最终得到红外报警器的六字节开启码。

三、算术编码示例

1.从二维码中提取的有效信息为:A1B2C3D4,则每个信号源出现的概率分别为A:0.1;B: 0.2; C: 0.3; D: 0.4;
2.将[0, 1)这个区间设置为初始间隔,则每个信号源所在的概率区间(在这里我们规定以A、B、C、D的顺序划分概率区间)为:
在这里插入图片描述
3.从RFID中提取的6组信号(在这里我们规定,按照数据读取的先后顺序进行排序)分别为:AAB、DCAB、CCB、ABCD、BCA、AC;

4.首先处理第一组信号,将信号源一个一个读入,先读入A.得到概率区间为[0,01);

5.重复步骤4,读入还是A,因为A在初始区间内是占整个区间的前10%, 因此对应的也是占上一次编码间隔的前10%,所以此时编码区间变为: [0,0.01)了;再然后我们读入B,B占整个区间的10%-30%,所以读入之后也占上一个编码区间的10%~30%, 读入之后得到新的编码操作区间为[0.001, 0.003);

6.通过公式计算得到第一组信号的报警码为0x02 (十进制为2);

7.重复步骤4、5、 6将6组信号全部处理完成,最终得到红外报警器的六字节开启码为: 0x02、0x38、 0x98、 0xD0、 0xA3、 0x04

8.附各组信号编码过程:
在这里插入图片描述

四、关键分析

在这里插入图片描述
设Low和High分别表示“当前间隔”的下边界和上边界,CodeRange为编码间隔的长度,LowRange(symbol)和HighRange(symbol)分别代表为了事件symbol分配的初始间隔下边界和上边界。上述过程的实现可用伪代码描述如下:

set Low to 0

set High to 1

while there are input symbols do

take a symbol

CodeRange = High – Low

High = Low + CodeRange *HighRange(symbol)

Low = Low + CodeRange * LowRange(symbol)

end of while

output Low

五、具体代码如下

import org.w3c.dom.ranges.Range;

import java.math.BigDecimal;

public class Ssbm {

    //private static Object Range;

    public static double getIndex(char s){

        char xinhaos[] = { 'A', 'B', 'C', 'D' };
        double gsilv[] = {0.1,0.2,0.3,0.4};
        for (int i = 0;i<xinhaos.length;i++){
            if (s==xinhaos[i]){
//                System.out.println(gsilv[i]);
                return gsilv[i];
            }
        }

        return 0;
    }

    public static double getLow(char s){

        char xinhaos[] = { 'A', 'B', 'C', 'D' };
        double gsilv[] = {0.0, 0.1,0.3,0.6};
        for (int i = 0;i<xinhaos.length;i++){
            if (s==xinhaos[i]){
                return gsilv[i];
            }
        }
        return 0;
    }
//    public static double getLcForLow(char res[]){
//        double Lc = 1;
//        for (int i=0;i< res.length-1;i++){
//            Lc = Lc * getIndex(res[i]);
//        }
//        return Lc;
//    }

    public static void getInfos() {
        String[] rresResult = {"AAB","DCAB","CCB","ABCD","BCA","AC"};

        for (int i =0;i<rresResult.length;i++){
//            String res[] = {"D", "C", "A","B"};
            char[] res =rresResult[i].toCharArray();
            double low = 0;
            double high =1;
            double codeRange = 0;
            double LowRange = 0;
            double range = 1.0;
            double zwl;
            //codeRange = getLcForLow(res);

            for (int j = 0; j < res.length; j++) {
                LowRange = getLow(res[j]);
                codeRange = getIndex(res[j]);
                range = high - low;
                low = add(low , mul(range,LowRange));
                high = add(low , mul(range,codeRange));
                //System.out.println(low);
                //System.out.println(high);
            }
            zwl = mul(add(low , high),Math.pow(10,res.length)/2)%256;
            String zwll= Integer.toHexString((int) zwl); //十进制转成十六进制
            System.out.println(zwll);
        }
    }
    public static double mul(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }
    public static double add(double v1,double v2){
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    public static double div(double v1,double v2,int scale){
        if(scale<0){
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public  static void main(String args[]){
//        System.out.println("hello world");
        //getIndex("B");
        //getHigh("A");
        //getLow("D");
        getInfos();
    }
}

发布了1 篇原创文章 · 获赞 2 · 访问量 50

猜你喜欢

转载自blog.csdn.net/Dimpies/article/details/103974206
今日推荐