首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ 算術編碼實現詳解:原理、區間更新與完整代碼實戰

     編輯:C++ 入門

算術編碼核心原理

將整個訊息序列編碼為 [0, 1) 區間內單一浮點數。核心參數:

  • 符號機率: 決定壓縮效率與初始區間劃分。
  • 編碼區間: 當前區間 [Low, High),隨符號處理持續縮小。

區間更新演算法

設 d = High - Low 為當前區間長度。第 i+1 個符號區間更新:

high = Low + d * 符號上限;
low  = Low + d * 符號下限;
High = high;
Low  = low;
d   *= 符號機率;

最終輸出 [Low, High) 區間內任一數值的二進位表示即為壓縮碼流。

完整 VC6.0 可編譯實現

#include <iostream>
#include <iomanip>
#define M 100  // 最大編碼長度
#define N 4    // 符號種類數

class ArithmeticCoder {
    int count, length;
    char symbol[N];
    long double prob[N];
    char code[M];
    long double High, Low, high, low, d;

public:
    ArithmeticCoder() : High(1.0), Low(0.0), d(1.0) {}

    void inputSymbols() {
        std::cout << "Input symbol and probability (e.g. a 0.5):\n";
        for (int i = 0; i < N; ++i) {
            std::cin >> symbol[i] >> prob[i];
        }
        count = N;
    }

    void inputCode() {
        std::cout << "Input code sequence: ";
        std::cin >> code;
        length = strlen(code);
    }

    void encode() {
        // 建立初始區間邊界
        long double cum = 0.0;
        long double upper[N], lower[N];
        for (int i = 0; i < count; ++i) {
            lower[i] = cum;
            cum += prob[i];
            upper[i] = cum;
        }

        // 逐符號編碼
        for (int k = 0; k < length; ++k) {
            int idx = -1;
            for (int i = 0; i < count; ++i)
                if (code[k] == symbol[i]) { idx = i; break; }
            if (idx == -1) { std::cerr << "Unknown symbol: " << code[k] << std::endl; return; }

            high = Low + d * upper[idx];
            low  = Low + d * lower[idx];
            High = high;
            Low  = low;
            d   *= prob[idx];

            std::cout << "Step " << k+1 << ": [" 
                      << std::setprecision(20) << Low << ", " << High << ")\n";
        }
        std::cout << "Final interval: [" << Low << ", " << High << ")\n";
        std::cout << "Compressed value (mid): " << (Low + High) / 2 << std::endl;
    }
};

int main() {
    ArithmeticCoder ac;
    ac.inputSymbols();
    ac.inputCode();
    ac.encode();
    return 0;
}

工程化關鍵點

現代 C++ 改良建議

  • 使用 std::vector, std::map 替代固定陣列。
  • 採用 uint64_t 整數算術編碼 (參考 range-v3 或 FastAC 實現)。
  • 模板化支援任意符號型別。
  • 加入單元測試驗證編解碼往返一致性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
挑戰解決方案
浮點精度不足使用 long double (80-bit) 或整數定點運算 (32/64-bit 移位實現)
區間過小導致下溢重新縮放:輸出確定位元,區間左移擴大
自適應機率模型動態更新符號計數,同步編碼/解碼端模型
位元流輸出緩衝位元,按位寫入檔案/網路流