数据压缩算法:旋转门算法(SDT)的C#实现
旋转门算法是一种比较快速的线性拟合算法,常常用于实时数据库中对数据进行压缩,使存储容量大大的减少。在实时数据库中,数据通常具有如下特点:
- 数据采集量大。
- 数据临近度高。如果不能对这些数据进行压缩,将对资源造成巨大的浪费。旋转门算法作为线性拟合的一种简便算法,具有效率高、压缩比高、实现简单、误差可控制的优点,现在已成为一种专门算法。
public struct point { public point(double pointx, double pointy) { this.x = pointx; this.y = pointy; } private double x; private double y; public double X { get { return x; } set { x = value; } } public double Y { get { return y; } set { y = value; } } }
public struct SDTPoints { private point currentData;//当前读取数据 private point lastReadData;//上一个读取数据 private point lastStoredData;//上一个保存数据 public point CurrentData { get { return currentData; } set { currentData = value; } } public point LastReadData { get { return lastReadData; } set { lastReadData = value; } } public point LastStoredData { get { return lastStoredData; } set { lastStoredData = value; } } }
public List<point> SDTcompress(List<point> originData, double AccuracyE,IProgress<int> progress,CancellationToken cancel)//后两个参数为其异步编程使用 { List<point> listSDT=new List<point>(); double upGate = -double.MaxValue; double downGate = double.MaxValue; double nowUp, nowDown;//当前数据的上下斜率 SDTPoints status=new SDTPoints(); if (originData.Count <= 0) return null; status.LastReadData = originData[0]; status.LastStoredData = status.LastReadData; listSDT.Add(status.LastReadData); int i = 0; foreach (var p in originData) { status.CurrentData = p; nowUp = (p.Y - status.LastStoredData.Y - AccuracyE)/(p.X - status.LastStoredData.X); if (nowUp > upGate) upGate = nowUp; nowDown = (p.Y - status.LastStoredData.Y + AccuracyE)/(p.X - status.LastStoredData.X); if (nowDown < downGate) downGate = nowDown; if (upGate >= downGate) { listSDT.Add(status.LastReadData);//保存前一个点 status.LastStoredData = status.LastReadData;//修改最近保存的点 upGate=(p.Y-status.LastStoredData.Y-AccuracyE)/ (p.X - status.LastStoredData.X); downGate = (p.Y - status.LastStoredData.Y + AccuracyE) / (p.X - status.LastStoredData.X); } status.LastReadData = p; i++; cancel.ThrowIfCancellationRequested(); progress?.Report(i * 100 / originData.Count ); } if (listSDT.Count == 1) { listSDT.Add(originData[originData.Count-1]); } return listSDT; }