Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1112030
  • 博文数量: 284
  • 博客积分: 8223
  • 博客等级: 中将
  • 技术积分: 3188
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-01 13:26
文章分类

全部博文(284)

文章存档

2012年(18)

2011年(33)

2010年(83)

2009年(147)

2008年(3)

分类: C/C++

2009-08-18 15:03:41

  对于数据压缩尝试过好多方法,比如基本的zip压缩(霍夫曼算法)、旋转门压缩算法、小波算法压缩、以及最后的shuffle压缩算法,这里总结如下,
  zip压缩:是无损压缩的基本方法,但对于跳变模拟量的压缩比较困难,文本压缩能力比较强。
  旋转门:有损压缩的压缩方法,但对于跳变比较大的数据压缩比较困难,该算法最大的优势在于运算速度。
  小波压缩:本身不具备压缩能力,只能在小波变换的过程中将趋近于0的直接当作0来进行变换,对于图形压缩能力比较强,代价是图形的分辨率降低。对于高精度的模拟量压缩感觉可用性不强。
  shuffle压缩:说白了,就是把模拟量数列重新进行排列。比如所有模拟量的32位放在一起,31位放在一起。。。
  这里,将shuffle算法的测试结果放在下面,供各位参考:
 
 
3600个数据进行测试(15k) float INT shuffle(float) shuffle(INT)
压缩率 压缩率 压缩率 压缩率
不变数据 (1K)100% (1K)100% (1K)100% (1K)100%
每个测试点数据都变化 线性变化 (6k)64% (12k)17% (1K)95% (2K)90%
折线变化 (7K)55% (10K)32% (2k)93% (2K)89%
(100左右)100以内随机数 (13k)18% (11k)30% (12k)21% (9k)43%
(100左右)10以内随机数 (12K)31% (9K)39% (10K)34% (7K)56%
(100左右)1以内随机数 (11K)47% (7K)52% (8K)46% (6k)62%
每5个测试数据变化一次 线性变化 (2K)90% (2K)87% (1K)96% (2K)91%
折线变化 (2K)88% (2K)87% (1k)95% (2K)91%
(100左右)100以内随机数 (4k)79% (3k)84% (5k)65% (4k)74%
(100左右)10以内随机数 (3k)82% (2k)87% (5k)70% (3k)80%
(100左右)1以内随机数 (3k)84% (2k)88% (4k)75% (3k)82%

 

下面将相关代码共享:

sem.c :用于生产float和int两种类型的数据文件

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>

static int maxLen = 3600;
static int tvLen = 1;
static double Range = 100;

void main(int argc,char **argv[])
{
   FILE *fd, *fd1;
   int i, ValidLen, tmp;
   char str[100];
   char ch[5]=",";
   
   fd = fopen("test", "w");
   fd1 = fopen("test1", "w");
   float value = 0;
   int vInt;
   unsigned char flag = 10;
   for(i=0;i<maxLen;i++){
      if(i%tvLen == 0) {
         value = 100+ ceil((drand48()-0.0)*Range*1000)/1000;
 // if(i
 //     else value = value -10;

 // value = 100.0+drand48()*Range;

         vInt = value*1000;
 // value = 0 + drand48()*Range;

         if(i<10||i>maxLen-10) {
             printf("%d : %f %d\n", i, value, vInt);
         }
      }
     // fwrite(&flag, sizeof(char), 1, fd);

      fwrite(&value, sizeof(float), 1, fd);
      fwrite(&vInt, sizeof(int), 1, fd1);

   }
   fclose(fd);
   fclose(fd1);
}

 

mo.c:用于进行shuffle算法,生成test2 test3文件,同时提供反shuffle算法。

 

#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>

#define maxLen 3600
void main(int argc,char **argv[])
{
   FILE *fd, *fd0,*fd1, *fd2;
   int i, j, iOut, jOut;
   
   unsigned vInt[maxLen], vFloat[maxLen];
   unsigned vOutInt[maxLen], vOutFloat[maxLen];
   unsigned vTmpInt[maxLen];
   int vPrintInt[maxLen];
   unsigned flag, flag2;
   
   fd = fopen("test", "r");
   fd0 = fopen("test1", "r");
   
   fd1 = fopen("test2", "w");
   fd2 = fopen("test3", "w");
   
 
   for(i=0;i<maxLen;i++){
      fread(&vFloat[i], sizeof(float), 1, fd);
      fread(&vInt[i], sizeof(unsigned), 1, fd0);
      vOutInt[i]=vOutFloat[i]=vTmpInt[i]=0;
           vPrintInt[i]=0;
   }

//对float部分数据进行shuffle算法

   flag = 1;
   for(i=0,iOut=0,jOut=0;i<sizeof(int)*8;i++) {
     for(j=0;j<maxLen;j++){
          if(vFloat[j]&flag) vOutFloat[jOut]+=1;

       iOut++;
       if(iOut==sizeof(int)*8) {
         iOut =0;
         jOut++;
       }else
      vOutFloat[jOut]=vOutFloat[jOut]<<1;
     }
     flag = flag<<1;
   }

   
//对int部分数据进行shuffle算法

   flag = 1;
   for(i=0,iOut=0,jOut=0;i<sizeof(int)*8;i++) {
     for(j=0;j<maxLen;j++){
          if(vInt[j]&flag) vOutInt[jOut]+=1;

       iOut++;
       if(iOut==sizeof(int)*8) {
         iOut =0;
         jOut++;
       }else
      vOutInt[jOut]=vOutInt[jOut]<<1;
     }
     flag = flag<<1;
   }
  //////////////////////////////////////////////////

   for(i=0;i<maxLen;i++){
      fwrite(&vOutFloat[i], sizeof(unsigned), 1, fd1);
      fwrite(&vOutInt[i], sizeof(unsigned), 1, fd2);
   }

   fclose(fd);
   fclose(fd0);
   
   fclose(fd1);
   fclose(fd2);
   /**************对Int洗牌算法以后的数据进行反算,检查算法是否能够复原********/
   
     flag = 0x80000000;
     flag2= 0x01;
    for(i=0,jOut=0;i<sizeof(int)*8;i++) {
     for(j=0;j<maxLen;j++){
          if(vOutInt[jOut]&flag) vTmpInt[j]+=flag2;
         
       if(flag==0x01) {
         jOut++;
         flag = 0x80000000;
       }else
      flag = flag >>1;
     }
     flag2 = flag2<<1;
   }

   memcpy(&vPrintInt[0],&vTmpInt[0], maxLen*sizeof(unsigned));
   for(i=0;i<maxLen;i++)
      if(i<10||i>maxLen-10) {
             printf("%d : %x %x %d\n", i, vOutInt[i], vTmpInt[i], vPrintInt[i]);
      }
}

makefile文件:

 

 

LIB = -lm -lz
all : clean sem mo
.PNHONY : all
clean :
    -rm *.o sem core *.zip test mo test1 test2
sem : sem.o
    cc -o sem sem.o $(LIB)
sem.o : sem.c
    cc -c sem.c $(LIB)
mo : mo.o
    cc -g -o mo mo.o $(LIB)
mo.o : mo.c
    cc -g -c mo.c $(LIB)

最后,将所有test test1 test2 test3 文件用系统命令压缩后,形成文章开始的表格。

可以看到,相关压缩算法中,将float先转换为int,再将数据使用shuffle算法重新排列,最后再用zip进行压缩,压缩效率比较高。

阅读(1202) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~