using System; using System.Collections.Generic; using System.Text; using System.Linq; namespace Misc { public class MyMath { /// /// 获取x 的下一个 以interval为倍数的 数 /// /// /// /// public static int ROUNDUP2(int x, int interval) { int i = x % interval; x += (interval - i); return x; } /// /// 解方程 ax²+bx+c=0 /// /// /// /// /// /// /// public static bool SolveAX2_BX_C(double a, double b, double c, out double x1, out double x2) { //ax²+bx+c=0(a≠0) //x=[-b±√(b²-4ac)]/2a if (a == 0) { if (b != 0) { x1 = x2 = -c / b; return true; } else { x1 = x2 = 0; return false; } } else { double q2 = b * b - 4 * a * c; if (q2 < 0) { x1 = x2 = 0; return false; } else { x1 = (-b + Math.Sqrt(q2)) / 2 / a; x2 = (-b - Math.Sqrt(q2)) / 2 / a; return true; } } } /// /// 排除 NULL_VALUE, 求最大值 /// /// /// public static int Max(IEnumerable buf) { return Max(buf, 0, buf.Count() - 1); } public static double Max(IEnumerable buf) { return Max(buf, 0, buf.Count() - 1); } /// /// 排除 NULL_VALUE, 求最大值 /// /// /// 开始序号 /// 结束序号 /// public static int Max(IEnumerable buf, int first, int last) { int max = MyBase.NULL_VALUE; for (int i = first; i <= last; i++) { if (MyBase.ISVALIDATA(buf.ElementAt(i))) { if (max == MyBase.NULL_VALUE) max = buf.ElementAt(i); else if (max < buf.ElementAt(i)) max = buf.ElementAt(i); } } return max; } public static double Max(IEnumerable buf, int first, int last) { double max = double.NaN; for (int i = first; i <= last; i++) { if (!double.IsNaN(buf.ElementAt(i))) { if (max == double.NaN) max = buf.ElementAt(i); else if (max < buf.ElementAt(i)) max = buf.ElementAt(i); } } return max; } /// /// 排除 NULL_VALUE, 求最小值 /// /// /// public static int Min(IEnumerable buf) { return Min(buf, 0, buf.Count() - 1); } public static double Min(IEnumerable buf) { return Min(buf, 0, buf.Count() - 1); } /// /// 排除 NULL_VALUE, 求最小值 /// /// /// 开始序号 /// 结束序号 /// public static int Min(IEnumerable buf, int first, int last) { int min = MyBase.NULL_VALUE; for (int i = first; i <= last; i++) { if (MyBase.ISVALIDATA(buf.ElementAt(i))) { if (min == MyBase.NULL_VALUE) min = buf.ElementAt(i); else if (min > buf.ElementAt(i)) min = buf.ElementAt(i); } } return min; } public static double Min(IEnumerable buf, int first, int last) { double min = double.NaN; for (int i = first; i <= last; i++) { if (!double.IsNaN(buf.ElementAt(i))) { if (min == double.NaN) min = buf.ElementAt(i); else if (min > buf.ElementAt(i)) min = buf.ElementAt(i); } } return min; } /// /// 排除 NULL_VALUE, 求平均值 /// /// /// public static int Avg(IEnumerable buf) { return Avg(buf, 0, buf.Count() - 1); } public static double Avg(IEnumerable buf) { return Avg(buf, 0, buf.Count() - 1); } /// /// 排除 NULL_VALUE, 求平均值 /// /// /// 开始序号 /// 结束序号 /// public static int Avg(IEnumerable buf, int first, int last) { int sum = 0; int cnt = 0; for (int i = first; i <= last; i++) { if ((i >= 0) && (i < buf.Count())) { if (MyBase.ISVALIDATA(buf.ElementAt(i))) { sum += buf.ElementAt(i); cnt++; } } } if (cnt != 0) return sum / cnt; else return MyBase.NULL_VALUE; } public static double Avg(IEnumerable buf, int first, int last) { double sum = 0; int cnt = 0; for (int i = first; i <= last; i++) { if ((i >= 0) && (i < buf.Count())) { if (!double.IsNaN(buf.ElementAt(i))) { sum += buf.ElementAt(i); cnt++; } } } if (cnt != 0) return sum / cnt; else return double.NaN; } /// /// 排除 NULL_VALUE, 求平均值, 无方向 last < first 也可以 /// /// /// 开始序号 /// 结束序号 /// public static int AvgNoDirection(IEnumerable buf, int first, int last) { int temp; if (first > last) { temp = first; first = last; last = temp; } return Avg(buf, first, last); } /// /// 排除 NULL_VALUE, 求Sigma /// /// /// 开始序号 /// 结束序号 /// public static int Sigma(IEnumerable buf, int first, int last) { int avg = Avg(buf, first, last); if (!MyBase.ISVALIDATA(avg)) return MyBase.NULL_VALUE; double sum = 0; int cnt = 0; for (int i = first; i <= last; i++) { if (MyBase.ISVALIDATA(buf.ElementAt(i))) { sum += (buf.ElementAt(i) - avg) * (buf.ElementAt(i) - avg); cnt++; } } if (cnt >= 3) return (int)(Math.Sqrt(sum / (cnt - 1))); else return 0; } /// /// 排除 NULL_VALUE, 求Sigma /// /// /// public static int Sigma(IEnumerable buf) { return Sigma(buf, 0, buf.Count() - 1); } static double Relevency(IEnumerable x, IEnumerable y) { return Relevency(x, 0, y, 0, x.Count()); } static double Relevency(IEnumerable x, int x_offset, IEnumerable y, int y_offset, int len) { double sum_x = 0; double sum_y = 0; double sum_x2 = 0; double sum_y2 = 0; double sum_xy = 0; int cnt = 0; ////避免溢出 //int max_x = Max(x, x_offset, x_offset + len - 1); //if (max_x > 30000) //{ //} for (int i = 0; i < len; i++) { int x_i = i + x_offset; int y_i = i + y_offset; if (MyBase.ISVALIDATA(x.ElementAt(x_i)) && MyBase.ISVALIDATA(y.ElementAt(y_i))) { sum_x += x.ElementAt(x_i); sum_y += y.ElementAt(y_i); sum_x2 += (double)x.ElementAt(x_i) * x.ElementAt(x_i); sum_y2 += (double)y.ElementAt(y_i) * y.ElementAt(y_i); sum_xy += (double)x.ElementAt(x_i) * y.ElementAt(y_i); cnt++; } } if (cnt > 0) { double s1 = cnt * sum_xy - sum_x * sum_y; double s2 = Math.Sqrt(cnt * sum_x2 - sum_x * sum_x); double s3 = Math.Sqrt(cnt * sum_y2 - sum_y * sum_y); double s4 = s1 / s2 / s3; return s4; } else return 0; } /// /// 求相关性 /// /// /// public static double Correl(IEnumerable x, IEnumerable y) { return Correl(x, 0, y, 0, x.Count()); } /// /// 求相关性 /// /// /// /// /// /// /// public static double Correl(IEnumerable x, int x_offset, IEnumerable y, int y_offset, int len) { double sum_x = 0; double sum_y = 0; double sum_x2 = 0; double sum_y2 = 0; double sum_xy = 0; int cnt = 0; ////避免溢出 //int max_x = Max(x, x_offset, x_offset + len - 1); //if (max_x > 30000) //{ //} for (int i = 0; i < len; i++) { int x_i = i + x_offset; int y_i = i + y_offset; double xv = x.ElementAt(x_i); double yv = y.ElementAt(y_i); if ((!double.IsNaN(xv)) && (!double.IsNaN(yv))) { sum_x += xv; sum_y += yv; sum_x2 += xv * xv; sum_y2 += yv * yv; sum_xy += xv * yv; cnt++; } } if (cnt > 0) { double s1 = cnt * sum_xy - sum_x * sum_y; double s2 = Math.Sqrt(cnt * sum_x2 - sum_x * sum_x); double s3 = Math.Sqrt(cnt * sum_y2 - sum_y * sum_y); double s4 = s1 / s2 / s3; return s4; } else return 0; } /// /// 求相关性 /// /// /// /// public static double Correl(IEnumerable x, IEnumerable y) { return Relevency(x, y); } /// /// 求相关性 /// /// /// /// /// /// /// public static double Correl(IEnumerable x, int x_offset, IEnumerable y, int y_offset, int len) { return Relevency(x, x_offset, y, y_offset, len); } /// /// 求2次拟合 a,b /// /// /// /// /// public static void Linest(IEnumerable y, IEnumerable x, out double a, out double b) { if (y.Count() != x.Count()) { throw new Exception("Linest() 参数异常 (y.Length=" + y.Count() + ") != (x.Length=" + x.Count() + ")"); } double sum_x = 0; double sum_y = 0; double sum_x2 = 0; double sum_xy = 0; int n = y.Count(); int cnt = 0; for (int i = 0; i < n; i++) { if (MyBase.ISVALIDATA(x.ElementAt(i)) && MyBase.ISVALIDATA(y.ElementAt(i))) { sum_xy += y.ElementAt(i) * x.ElementAt(i); sum_x2 += x.ElementAt(i) * x.ElementAt(i); sum_x += x.ElementAt(i); sum_y += y.ElementAt(i); cnt++; } } if (cnt > 1) { a = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x); b = sum_y / n - a * sum_x / n; } else { a = 1; b = 0; } } public static void Linest(IEnumerable y, IEnumerable x, out double a, out double b) { if (y.Count() != x.Count()) { throw new Exception("Linest() 参数异常 (y.Length=" + y.Count() + ") != (x.Length=" + x.Count() + ")"); } double sum_x = 0; double sum_y = 0; double sum_x2 = 0; double sum_xy = 0; int n = y.Count(); int cnt = 0; for (int i = 0; i < n; i++) { if (!double.IsNaN(x.ElementAt(i)) && !double.IsNaN(y.ElementAt(i))) { sum_xy += y.ElementAt(i) * x.ElementAt(i); sum_x2 += x.ElementAt(i) * x.ElementAt(i); sum_x += x.ElementAt(i); sum_y += y.ElementAt(i); cnt++; } } if (cnt > 1) { a = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x * sum_x); b = sum_y / n - a * sum_x / n; } else { a = 1; b = 0; } } /// /// 对环形数据 分区移位 /// /// 原始数据 /// key=old_idx, value=new_idx /// public static int[] Map(IEnumerable data, Dictionary map) { if (map == null || map.Count() == 0) return data.ToArray(); int[] data_new = new int[data.Count()]; if (map.Count() == 1) { //只是平移而已 int old_idx0 = map.Keys.ElementAt(0); int new_idx0 = map[old_idx0]; for (int i = 0; i < data.Count(); i++) { int new_idx = i; int old_idx = (old_idx0 - new_idx0) + new_idx; if (old_idx >= data.Count()) old_idx -= data.Count(); else if (old_idx < 0) old_idx += data.Count(); data_new[new_idx] = data.ElementAt(old_idx); } return data_new; } for (int i = 0; i < map.Count(); i++) { int old_idx0 = map.Keys.ElementAt(i); int new_idx0 = map[old_idx0]; int i_next = i + 1; if (i_next >= map.Count()) i_next = 0; int old_idx1 = map.Keys.ElementAt(i_next); int new_idx1 = map[old_idx1]; int cnt = new_idx1 - new_idx0; if (cnt < 0) cnt += data.Count(); int cnt_old = old_idx1 - old_idx0; if (cnt_old < 0) cnt_old += data.Count(); double w = 1.0 * cnt_old / cnt; for (int j = 0; j < cnt; j++) { int new_idx = j + new_idx0; if (new_idx >= data.Count()) new_idx -= data.Count(); double old_idx = j * w + old_idx0; int o1 = (int)Math.Ceiling(old_idx); int o0 = (int)old_idx; if (o0 == o1) { int old_idx_0 = o0; if (old_idx_0 >= data.Count()) old_idx_0 -= data.Count(); data_new[new_idx] = data.ElementAt(old_idx_0); } else { int old_idx_0 = o0; if (old_idx_0 >= data.Count()) old_idx_0 -= data.Count(); int old_idx_1 = o1; if (old_idx_1 >= data.Count()) old_idx_1 -= data.Count(); if (MyBase.ISVALIDATA(data.ElementAt(old_idx_1)) && MyBase.ISVALIDATA(data.ElementAt(old_idx_0))) { data_new[new_idx] = (int)(data.ElementAt(old_idx_1) * (old_idx - o0) + data.ElementAt(old_idx_0) * (o1 - old_idx)); } else if (MyBase.ISVALIDATA(data.ElementAt(old_idx_0))) { data_new[new_idx] = data.ElementAt(old_idx_0); } else if (MyBase.ISVALIDATA(data.ElementAt(old_idx_1))) { data_new[new_idx] = data.ElementAt(old_idx_1); } else { data_new[new_idx] = MyBase.NULL_VALUE; } } } } return data_new; } /// /// 对环形数据 分区移位 /// /// 原始数据 /// key=old_idx, value=new_idx /// public static double[] Map(IEnumerable data, Dictionary map) { if (map == null || map.Count() == 0) return data.ToArray(); double[] data_new = new double[data.Count()]; if (map.Count() == 1) { //只是平移而已 int old_idx0 = map.Keys.ElementAt(0); int new_idx0 = map[old_idx0]; for (int i = 0; i < data.Count(); i++) { int new_idx = i; int old_idx = (old_idx0 - new_idx0) + new_idx; if (old_idx >= data.Count()) old_idx -= data.Count(); else if (old_idx < 0) old_idx += data.Count(); data_new[new_idx] = data.ElementAt(old_idx); } return data_new; } for (int i = 0; i < map.Count(); i++) { int old_idx0 = map.Keys.ElementAt(i); int new_idx0 = map[old_idx0]; int i_next = i + 1; if (i_next >= map.Count()) i_next = 0; int old_idx1 = map.Keys.ElementAt(i_next); int new_idx1 = map[old_idx1]; int cnt = new_idx1 - new_idx0; if (cnt < 0) cnt += data.Count(); int cnt_old = old_idx1 - old_idx0; if (cnt_old < 0) cnt_old += data.Count(); double w = 1.0 * cnt_old / cnt; for (int j = 0; j < cnt; j++) { int new_idx = j + new_idx0; if (new_idx >= data.Count()) new_idx -= data.Count(); double old_idx = j * w + old_idx0; int o1 = (int)Math.Ceiling(old_idx); int o0 = (int)old_idx; if (o0 == o1) { int old_idx_0 = o0; if (old_idx_0 >= data.Count()) old_idx_0 -= data.Count(); data_new[new_idx] = data.ElementAt(old_idx_0); } else { int old_idx_0 = o0; if (old_idx_0 >= data.Count()) old_idx_0 -= data.Count(); int old_idx_1 = o1; if (old_idx_1 >= data.Count()) old_idx_1 -= data.Count(); if (!double.IsNaN(data.ElementAt(old_idx_1)) && !double.IsNaN(data.ElementAt(old_idx_0))) { data_new[new_idx] = (data.ElementAt(old_idx_1) * (old_idx - o0) + data.ElementAt(old_idx_0) * (o1 - old_idx)); } else if (!double.IsNaN(data.ElementAt(old_idx_0))) { data_new[new_idx] = data.ElementAt(old_idx_0); } else if (!double.IsNaN(data.ElementAt(old_idx_1))) { data_new[new_idx] = data.ElementAt(old_idx_1); } else { data_new[new_idx] = double.NaN; } } } } return data_new; } } }