using Misc; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FLY.FeedbackRenZiJia.Common { public static class MyMath { #region 数列操作 /// <summary> /// 转为 % 数据,单位 % /// </summary> /// <param name="data"></param> /// <returns></returns> public static int[] GetPercent(int[] data) { int avg = Misc.MyMath.Avg(data); int[] percent = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { if (Misc.MyBase.ISVALIDATA(data[i])) { percent[i] = 100 * (data[i] - avg) / avg; } else { percent[i] = Misc.MyBase.NULL_VALUE; } } return percent; } /// <summary> /// 两列数据相减 /// </summary> /// <param name="data1"></param> /// <param name="data2"></param> /// <returns></returns> public static int[] GetDiff(int[] data1, int[] data2) { int[] diff = new int[data1.Count()]; for (int i = 0; i < data1.Count(); i++) { if (Misc.MyBase.ISVALIDATA(data1[i]) && Misc.MyBase.ISVALIDATA(data2[i])) { diff[i] = data1[i] - data2[i]; } else { diff[i] = Misc.MyBase.NULL_VALUE; } } return diff; } /// <summary> /// 两列数据中间值 /// </summary> /// <param name="data1"></param> /// <param name="data2"></param> /// <returns></returns> public static int[] GetMid(int[] data1, int[] data2) { int[] mid = new int[data1.Count()]; for (int i = 0; i < data1.Count(); i++) { if (Misc.MyBase.ISVALIDATA(data1[i]) && Misc.MyBase.ISVALIDATA(data2[i])) { mid[i] = (data1[i] + data2[i]) / 2; } else { mid[i] = Misc.MyBase.NULL_VALUE; } } return mid; } /// <summary> /// 上下平移,使平均值为0 /// </summary> /// <param name="data"></param> /// <returns></returns> public static int[] OffsetAvgBe0(int[] data) { int avg = Misc.MyMath.Avg(data); int[] data_out = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { if (Misc.MyBase.ISVALIDATA(data[i])) { data_out[i] = data[i] - avg; } else { data_out[i] = Misc.MyBase.NULL_VALUE; } } return data_out; } /// <summary> /// 放大数量 /// </summary> /// <param name="data"></param> /// <param name="z"></param> /// <returns></returns> public static int[] ZoomIn(int[] data, int z) { if (z == 1) { return data.Clone() as int[]; } int[] data_out = new int[data.Count() * z]; for (int i = 0; i < data.Count(); i++) { for (int j = 0; j < z; j++) data_out[i * z + j] = data[i]; } return data_out; } /// <summary> /// 缩小数量 /// </summary> /// <param name="data"></param> /// <param name="z"></param> /// <returns></returns> public static int[] ZoomOut(int[] data, int z) { if (z == 1) { return data.Clone() as int[]; } int[] data_out = new int[data.Count() / z]; for (int i = 0; i < data_out.Count(); i++) { data_out[i] = Misc.MyMath.Avg(data, i * z, (i + 1) * z - 1); } return data_out; } /// <summary> /// 滤波操作 /// </summary> /// <param name="data">数据源</param> /// <param name="cell">滤波器</param> /// <returns></returns> public static int[] Filter(int[] data, int[] cell) { if (cell == null || cell.Count()==0) { return data.Clone() as int[]; } int[] data_out = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { int sum = 0; int cnt = 0; for (int j = 0; j < cell.Count(); j++) { int idx = i - cell.Count() / 2 + j; if (idx < 0) idx += data.Count(); else if (idx >= data.Count()) idx -= data.Count(); if (Misc.MyBase.ISVALIDATA(data[idx])) { sum += data[idx] * cell[j]; cnt += cell[j]; } } if (cnt > 0) { data_out[i] = sum / cnt; } else { data_out[i] = Misc.MyBase.NULL_VALUE; } } return data_out; } /// <summary> /// 数据 放大 /// </summary> /// <param name="data"></param> /// <param name="z">放大倍数</param> /// <returns></returns> public static int[] ZoomY(int[] data, double z) { if (z == 1 ) { return data.Clone() as int[]; } int[] data_out = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { if (Misc.MyBase.ISVALIDATA(data[i])) { data_out[i] = (int)(data[i] * z); } else { data_out[i] = Misc.MyBase.NULL_VALUE; } } return data_out; } /// <summary> /// 滤波操作,均值滤波 /// </summary> /// <param name="data">数据源</param> /// <param name="cell">滤波器宽度</param> /// <returns></returns> public static int[] Filter(int[] data, int cell_width) { int[] data_out = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { int sum = 0; int cnt = 0; for (int j = 0; j < cell_width; j++) { int idx = i - cell_width / 2 + j; if (idx < 0) idx += data.Count(); else if (idx >= data.Count()) idx -= data.Count(); if (Misc.MyBase.ISVALIDATA(data[idx])) { sum += data[idx]; cnt += 1; } } if (cnt > 0) { data_out[i] = sum / cnt; } else { data_out[i] = Misc.MyBase.NULL_VALUE; } } return data_out; } /// <summary> /// 通过data2 平移,找到与 data1 最相似的位置, data1 与 data2 必须大小一致 /// </summary> /// <param name="data1"></param> /// <param name="data2"></param> /// <param name="range_percent">0~1</param> /// <param name="offset"></param> /// <param name="r"></param> public static void CalBestMove(int[] data1, int[] data2, double range_percent, out int data2_move, out double max_r) { if (data1.Length != data2.Length) { throw new Exception("CalBestMove() 参数错误 (data1.Length = " + data1.Length.ToString() + ")!=(data2.Length =" + data2.Length.ToString() + ")"); } if ((range_percent > 1) || (range_percent < 0)) { throw new Exception("CalBestMove() 参数错误 range_percent = " + range_percent.ToString() + " 异常"); } int range = (int)(Math.Ceiling(range_percent * data1.Length)); if (range <= 0) range = 1; double mr = 0; int mi = -1; for (int i = -range; i <= range; i++) { int[] data22 = Move(data2, i); double r = Misc.MyMath.Correl(data1, data22); if (mi == -1) { mr = r; mi = i; } else { if (r > mr) { mr = r; mi = i; } } } //找到了!!! max_r = mr; data2_move = mi; } /// <summary> /// 平移 /// </summary> /// <param name="data">原始厚度数组</param> /// <param name="move">平移量 向右移动为正</param> public static int[] Move(int[] data, int move) { if (move == 0) { //什么都不用做 return data.Clone() as int[]; } int cnt = data.Count(); int[] data_out = new int[cnt]; for (int i = 0; i < cnt; i++) { int idx = i - move; if (idx >= cnt) idx -= cnt; else if (idx < 0) idx += cnt; data_out[i] = data[idx]; } return data_out; } /// <summary> /// 计算极差 /// </summary> /// <param name="data"></param> public static int CalMaxMin(int[] data) { int max = Misc.MyMath.Max(data); int min = Misc.MyMath.Min(data); if (Misc.MyBase.ISVALIDATA(max)) { return max - min; } return 0; } /// <summary> /// X轴放大 /// </summary> /// <param name="data"></param> /// <param name="mid">中心位置</param> /// <param name="z"></param> /// <returns></returns> public static int[] ZoomX(int[] data, int mid, double z) { if ( Math.Abs(z - 1)<0.001 ) { return data.Clone() as int[]; } //放大 int[] _diff = new int[data.Count()]; for (int i = 0; i < data.Count(); i++) { double new_offset = i - (mid); if (Math.Abs(new_offset) > data.Count() / 2) { if (new_offset > 0) new_offset -= data.Count(); else new_offset += data.Count(); } double old_offset = new_offset * 1 / z; if (Math.Abs(old_offset) > data.Count() / 2) { //没数据了 _diff[i] = Misc.MyBase.NULL_VALUE; } else { int d1 = (int)Math.Ceiling(old_offset); int d2 = (int)Math.Floor(old_offset); double p1 = old_offset - d2; double p2 = d1 - old_offset; d1 += (mid); if (d1 >= data.Count()) d1 -= data.Count(); else if (d1 < 0) d1 += data.Count(); d2 += (mid); if (d2 >= data.Count()) d2 -= data.Count(); else if (d2 < 0) d2 += data.Count(); if (d1 == d2) { _diff[i] = data[d1]; } else { if (Misc.MyBase.ISVALIDATA(data[d1]) && Misc.MyBase.ISVALIDATA(data[d2])) _diff[i] = (int)(data[d1] * p1 + data[d2] * p2); else if (Misc.MyBase.ISVALIDATA(data[d1])) _diff[i] = data[d1]; else _diff[i] = data[d2]; } } } return _diff; } public static double BreakUp(int[] data) { int avg = Misc.MyMath.Avg(data); Dictionary<Range, bool> block = new Dictionary<Range, bool>(); Range range = new Range(); bool isBigger = false; for (int i = 0; i < data.Count(); i++) { int idx = i; if (range.IsValid) { if (data[idx] == avg) { //切换点 block.Add(range, isBigger); range = new Range(); } else if ((data[idx] > avg)) { if (isBigger) range.End = idx; else { //切换点 block.Add(range, isBigger); range = new Range() { Begin = idx, End = idx }; isBigger = true; } } else { if (!isBigger) range.End = idx; else { //切换点 block.Add(range, isBigger); range = new Range() { Begin = idx, End = idx }; isBigger = false; } } } else { if (data[idx] == avg) { } else if ((data[idx] > avg)) { range = new Range() { Begin = idx, End = idx }; isBigger = true; } else { range = new Range() { Begin = idx, End = idx }; isBigger = false; } } } Range f = block.Keys.First(); bool fb = block[f]; Range l = block.Keys.Last(); bool lb = block[l]; if (fb == lb) { //可能一起的 if ((f.Begin == 0) && (l.End == data.Count() - 1)) { //同一块 f.End += l.Width; block.Remove(l); } } double block_width_max = block.Keys.Max((r) => { return r.Width; }); return block_width_max / data.Count(); } public static Range[] Break(int[] data) { int avg = Misc.MyMath.Avg(data); Dictionary<Range, bool> block = new Dictionary<Range, bool>(); Range range = new Range(); bool isBigger = false; for (int i = 0; i < data.Count(); i++) { int idx = i; if (range.IsValid) { if (data[idx] == avg) { //切换点 block.Add(range, isBigger); range = new Range(); } else if ((data[idx] > avg)) { if (isBigger) range.End = idx; else { //切换点 block.Add(range, isBigger); range = new Range() { Begin = idx, End = idx }; isBigger = true; } } else { if (!isBigger) range.End = idx; else { //切换点 block.Add(range, isBigger); range = new Range() { Begin = idx, End = idx }; isBigger = false; } } } else { if (data[idx] == avg) { } else if ((data[idx] > avg)) { range = new Range() { Begin = idx, End = idx }; isBigger = true; } else { range = new Range() { Begin = idx, End = idx }; isBigger = false; } } } if (block.Count() == 0) { return null; } else if (block.Count() > 1) { Range f = block.Keys.First(); bool fb = block[f]; Range l = block.Keys.Last(); bool lb = block[l]; if (fb == lb) { //可能一起的 if ((f.Begin == 0) && (l.End == data.Count() - 1)) { //同一块 //f.Begin变为负数 f.Begin = f.Begin - l.Width; block.Remove(l); } } } return block.Keys.ToArray(); } #endregion } }