//門一旦打開就不關閉,是指在一個壓縮段內。
說明:該算法的壓縮效果和數據有很大關系,一般測試時用正弦波數據,壓縮效果很好,如果用隨機數,基本不會壓縮。
==============================
程序說明:
E(壓縮精度)的值要根據待壓縮的數值來定,如果E的值太小,解壓誤差會很小,但壓縮率低。
如果E的值太大,壓縮比非常高,100MB的文件可能就只有幾M,但解壓誤差非常大。所以E要多試幾次取一個比較合理的值。
5.解壓過程:(線性插值)有起點和終點坐標可以求出線段的公式,然后根據某點x軸坐標求出其對應的y的值,也就是實際的值。
=====================
#include <stdio.h> #define MAX_DOUBLE 1.79769e+308 #define E 3 struct point { int x, y; }; void compress() { FILE * fin = fopen("rand.txt", "r"); FILE * fout = fopen("out.txt", "w"); //上門和下門,初始時門是關着的 double up_gate = -MAX_DOUBLE; double down_gate = MAX_DOUBLE; //當前數據的上斜率和下斜率 double now_up, now_down; int data; //當前讀取到的數據 int last_read_data; //當前數據的前一個數據 int last_stored_data; //最近保存的點 //read and save the first data fscanf(fin, "%d", &last_stored_data); fprintf(fout, "0 %d ", last_stored_data); last_read_data = last_stored_data; int last_stored_t = 0; //最近保存數據的時間,init 0 //循環處理數據 int t=0; while(++t, fscanf(fin, "%d", &data) != EOF) { now_up = double(data-last_stored_data-E) / (t-last_stored_t); if(now_up > up_gate) up_gate = now_up; now_down = double(data-last_stored_data+E) / (t-last_stored_t); if(now_down < down_gate) down_gate = now_down; if(up_gate >= down_gate) { //保存前一個點 fprintf(fout, "%d %d ", t-1, last_read_data); last_stored_t = t-1; //修改最近保存數據時間點 last_stored_data = last_read_data; //初始化兩扇門為當前點與上個點的斜率 up_gate = double(data-last_stored_data-E); down_gate = double(data-last_stored_data+E); } last_read_data = data; } // sava end point fprintf(fout, "%d %d ", t-1, last_read_data); fclose(fin); fclose(fout); } void uncompress() { FILE * fin = fopen("out.txt", "r"); FILE * fout = fopen("src.txt", "w"); point a,b; fscanf(fin, "%d %d", &a.x, &a.y); while(fscanf(fin, "%d %d", &b.x,&b.y) != EOF) { //Step.1 fprintf(fout, "%d ", a.y); //Step.2 if(a.x+1 != b.x) { double k = double(b.y - a.y) / (b.x - a.x); //計算斜率 for(int i=a.x+1; i<b.x; i++) { //線性插值求被壓縮掉的數據 fprintf(fout, "%.0lf ", k*(i-a.x) + a.y); } } a.x = b.x; a.y = b.y; } fprintf(fout, "%d ", b.y); fclose(fin); fclose(fout); } int main(void) { compress(); uncompress(); return 0; }
其實把current , lastRead, lastStored定義為Point類型程序會更清晰。
下面上一下壓縮效果圖,界面是用.Net中的Chart控件做的,用法很簡單,如果想直觀的看到結果,你們可以托一個控件上去看看效果~ 挺好玩的。
上面的曲線是原數據,總共是800個點,壓縮后可以看到,儲存的點屈指可數。
從圖中可以看出對均勻變化的數據壓縮效果是非常好的,但是隨機數基本上不會被壓縮,圖就不貼了。
轉自:http://blog.csdn.net/gneveek/article/details/7821151