算術編碼例題:
假設信源信號有{A, B, C, D}四個,他們的概率分別為{0.1, 0.4, 0.2, 0.3},如果我們要對CADACDB這個信號進行編碼,那么應該怎樣進行呢?
准備工作完成之后,我們便可以開始進行編碼了。
那么我們首先讀入信號:C——因為C在最初始的間隔中是[0.5, 0.7),所以讀入C之后我們的編碼間隔就變成[0.5, 0.7)了;
緊接着,我們讀入的是A,A在初始區間內是占整個區間的前10%,因此對應這個上來也是需要占這個編碼間隔的前10%,因此編碼區間變為:[0.5, 0.52)了;
再然后是D,因為D占整個區間的70% ~ 100%,所以也是占用這個編碼區間的70% ~ 100%,操作后的編碼區間為[0.514, 0.52)
……
直到最后將信號量全部讀出。
最后,我們將這個操作過程繪制成為一張表:
解碼例題:
假設信源信號有{A, B, C, D}四個,他們的概率分別為{0.1, 0.4, 0.2, 0.3},當我們得到的編碼是0.5143876的時候,問原始的信號串(7位)是怎樣的?
准備工作完成之后,我們現在開始解碼:
我們發現,待解碼的數據0.5143876在[0.5, 0.7)內,因此,我們解出的第一個碼值為C
同理,我們繼續計算0.5143876處於[0.5, 0.7)的第一個10%內因此解出的第二個碼值為A
……
這個過程持續直到執行七次全部執行完為止。
那么以上的過程我們同樣可以列表表示:
作業:對任一概率序列,實現算術編碼,碼長不少於16位,不能固定概率,語言自選。
基於Python實現:

from collections import Counter #統計列表出現次數最多的元素 import numpy as np print("Enter a Sequence\n") inputstr = input() print (inputstr + "\n") res = Counter(inputstr) #統計輸入的每個字符的個數,res是一個字典類型 print (str(res)) # print(res) #sortlist = sorted(res.iteritems(), lambda x, y : cmp(x[1], y[1]), reverse = True) #print sortlist M = len(res) #print (M) N = 5 A = np.zeros((M,5),dtype=object) #生成M行5列全0矩陣 #A = [[0 for i in range(N)] for j in range(M)] reskeys = list(res.keys()) #取字典res的鍵,按輸入符號的先后順序排列 # print(reskeys) resvalue = list(res.values()) #取字典res的值 totalsum = sum(resvalue) #輸入一共有幾個字符 # Creating Table A[M-1][3] = 0 for i in range(M): A[i][0] = reskeys[i] #第一列是res的鍵 A[i][1] = resvalue[i] #第二列是res的值 A[i][2] = ((resvalue[i]*1.0)/totalsum) #第三列是每個字符出現的概率 i=0 A[M-1][4] = A[M-1][2] while i < M-1: #倒數兩列是每個符號的區間范圍,與輸入符號的順序相反 A[M-i-2][4] = A[M-i-1][4] + A[M-i-2][2] A[M-i-2][3] = A[M-i-1][4] i+=1 print (A) # Encoding print("\n------- ENCODING -------\n" ) strlist = list(inputstr) LEnco = [] UEnco = [] LEnco.append(0) UEnco.append(1) for i in range(len(strlist)): result = np.where(A == reskeys[reskeys.index(strlist[i])]) #滿足條件返回數組下標(0,0),(1,0) addtollist = (LEnco[i] + (UEnco[i] - LEnco[i])*float(A[result[0],3])) addtoulist = (LEnco[i] + (UEnco[i] - LEnco[i])*float(A[result[0],4])) LEnco.append(addtollist) UEnco.append(addtoulist) tag = (LEnco[-1] + UEnco[-1])/2.0 #最后取區間的中點輸出 LEnco.insert(0, " Lower Range") UEnco.insert(0, "Upper Range") print(np.transpose(np.array(([LEnco],[UEnco]),dtype=object))) #np.transpose()矩陣轉置 print("\nThe Tag is \n ") print(tag) # Decoding print("\n------- DECODING -------\n" ) ltag = 0 utag = 1 decodedSeq = [] for i in range(len(inputstr)): numDeco = ((tag - ltag)*1.0)/(utag - ltag) #計算tag所占整個區間的比例 for i in range(M): if (float(A[i,3]) < numDeco < float(A[i,4])): #判斷是否在某個符號區間范圍內 decodedSeq.append(str(A[i,0])) ltag = float(A[i,3]) utag = float(A[i,4]) tag = numDeco print("The decoded Sequence is \n ") print("".join(decodedSeq))
參考:
https://blog.csdn.net/qq_36752072/article/details/77986159
https://github.com/nishanpoojary/Arithmetic-Coding