【转】旋转门算法

//门一旦打开就不关闭,是指在一个压缩段内。

说明:该算法的压缩效果和数据有很大关系,一般测试时用正弦波数据,压缩效果很好,如果用随机数,基本不会压缩。

==============================

程序说明:

 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

原文地址:https://www.cnblogs.com/budapeng/p/4963350.html