手记

算术编码,是图像压缩的主要算法之一

package com.xxd.arithmetics;

import java.util.Scanner;

public class ArithmeticCode {
    public Scanner sc = new Scanner(System.in);// 控制台输入对象
    public Unit[] arrU = new Unit[4];// 用以存储符号概率对象
    public int step = 1;

    public ArithmeticCode() {
        arrU[1] = new Unit("00", 0, 0.1);
        arrU[0] = new Unit("01", 0.1, 0.5);
        arrU[2] = new Unit("10", 0.5, 0.7);
        arrU[3] = new Unit("11", 0.7, 1);

    }

    // 编码过程
    public double Coder() {

        double gNum = 0; // 用于存储信息码的值
        // 左边界值和右边界值,以及左右边界值的差值
        double left = 0, right = 1, d = 1;
        Unit u1 = new Unit();

        while (true) {
            String flag = sc.next();
            if (flag.equalsIgnoreCase("exit")) {
                return gNum;
            }
            u1 = query(flag);
            left += d * u1.lVal;
            right = left + d * u1.p;
            gNum = left + (Math.random() * d * u1.p);
            d = d * u1.p;
            this.step++;
            /*
             * System.out.println("左值为"+left); System.out.println("中值为"+d);
             * System.out.println("右值为"+right);
             */

        }
    }

    // 解码过程
    public String deCoder(double n) {
        int j = 7, i = 0;
        double gNum = n;
        String[] str = new String[j];
        double left = 0, right = 1, d = 1;
        Unit u1 = new Unit();

        while (j > 0) {
            for (Unit u2 : arrU) {
                double ltmp = left + d * u2.lVal;
                double rtmp = ltmp + d * u2.p;
                if (ltmp <= gNum && gNum < rtmp) {
                    u1 = u2;
                    str[i++] = u1.name;
                }
            }
            left += d * u1.lVal;
            right = left + d * u1.p;
            d = d * u1.p;
            j--;
        }
        return join(str, " ");
    }

    // 将数组中元素插入指定字符串
    public String join(String[] arr, String jStr) {
        String newStr = "";
        for (int i = 0; i < arr.length; i++) {
            if (i != arr.length - 1) {
                newStr += arr[i] + jStr;
            } else {
                newStr += arr[i];
            }
        }
        return newStr;
    }

    // 查询输入符号
    public Unit query(String name) {

        for (Unit unit : arrU) {
            if (name.equals(unit.name)) {
                return unit;
            }
        }

        return null;
    }

    public static void main(String[] args) {

        ArithmeticCode ac = new ArithmeticCode();
        System.out.println("----请输入符号(如要退出请输入exit)----");
        double codeVal = ac.Coder();
        System.out.println("====输入结束====");
        System.out.println("\n生成信息码为:" + codeVal);
        System.out.println("\n----开始解码----");
        System.out.println(ac.deCoder(codeVal));
        System.out.println("----解码结束----");

    }

}

// 创建一个初始码类:Unit
class Unit {

    public String name;// 符号
    public double lVal;// 初始码概率的左边界值
    public double rVal;// 初始码概率的右边界值
    public double p;// 初始码概率值

    public Unit() {
    };

    public Unit(String name, double lVal, double rVal) {
        this.name = name;
        this.lVal = lVal;
        this.rVal = rVal;
        this.p = this.rVal - this.lVal;
    }
}
1人推荐
随时随地看视频
慕课网APP