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;
}
}
}