概述
1.最近参与两个界面项目的制作,主要负责底层算法逻辑
2.任务一可分解为一个算法题。
水包温升计算:给定一些离散的仿真数据,希望得到连续的数据,具体而言是一个三维线性插值。
输入:
B=[4 10]
H=[5 8]
Q=[8 12]
其中B为水包内流道高度(mm),H为水包内流道与散热面距离(mm),Q为水流量(L/min),输出水包最高温度。
输出:
需要最终能在程序中输入B在5至8mm、H在4至10mm以及流量Q在8至12L/min内的任意一组数值能得到一个最大温升的结果。其中最大温升为输出水包的最高温度减去40℃。
双线性插值算法如下
采用的是二分查找,对每一维数据B、H、Q,在其输入区间的任意处都有对应的水包温度,大体思路是采用双线性插值进行处理。
InterAlgorithm类
实现单维双线性插值
首先看binarySearch()函数,对输入的key值进行二分查找,找到其对应数值的在数组中索引区间[index,index+1],依据此找到key值对应的Xnear,Ynear,Xnear即为key值所在所在的区间,Ynear为key对应数值所在的区间。最后调用双线性插值getValue()函数实现插值计算。
public class InterAlgorithm
{
/// <summary>
/// 计算插值结果,克服二分查找右区间端点无法插值
/// </summary>
/// <param name="x_Values"></param>
/// <param name="y_Values"></param>
/// <param name="key"></param>
/// <returns></returns>
public static double Compute(double[] x_Values, double[] y_Values, double key)
{
int index = binarySearch(x_Values, key);
double[] Xnear = { };//key隶属区间
double[] Ynear = { };//key对应的value的隶属区间
if (index == -1)
{
throw new IndexOutOfRangeException("超过插值范围");
}
if (index == x_Values.Length-1)
{
double t = 0;
t = y_Values[index];
return Math.Round(t,3);
}
Xnear = new double[2] { x_Values[index], x_Values[index+1] };
Ynear = new double[2] { y_Values[index], y_Values[index+1] };
return Math.Round(getValue(Xnear, Ynear, key), 3);
}
/// <summary>
/// 通过key值索引获取的x_map,y_map;计算单维线性插值结果
/// </summary>
/// <param name="x_map"></param>
/// <param name="y_map"></param>
/// <param name="key"></param>
/// <returns></returns>
private static double getValue(double[] x_map, double[] y_map, double key)
{
double x_Avg = GetAverage(x_map);
double y_Avg = GetAverage(y_map);
double forecast = 0f;
double b = 0f;
double a = 0f;
double tempTop = 0f;
double tempBottom = 0f;
for (int i = 0; i < y_map.Length; i++)
{
tempTop += (x_map[i] - x_Avg) * (y_map[i] - y_Avg);
tempBottom += Math.Pow(((x_map[i] - x_Avg)), 2f);
}
b = tempTop / tempBottom;
a = y_Avg - b * x_Avg;
forecast = a + b * key;
return forecast;
}
/// <summary>
/// 得到平均值
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private static double GetAverage(double[] data)
{
double total = 0;
for (int i = 0; i < data.Length; i++)
{
total += data[i];
}
return total / data.Length;
}
/// <summary>
/// 二分查找,查找输入key(x)对应的数组索引
/// </summary>
/// <param name="dlist"></param>
/// <param name="x"></param>
/// <returns></returns>
public static int binarySearch(double[] dlist, double x)
{
if (x < dlist[0] || x >dlist[dlist.Length - 1]) return -1;
int low = 0;
int high = dlist.Length - 1;
while (low <= high)
{
int middle = (low + high) / 2;
if (middle == dlist.Length - 1)
{
return middle;
}
if (dlist[middle] == x)
{
return middle;
}
else
{
if (dlist[middle] < x)
{
if (x < dlist[middle + 1])
{
return middle;
}
else
{
low = middle + 1;
continue;
}
}
else
{
if (x > dlist[middle - 1])
{
return middle - 1;
}
else
{
high = middle - 1;
continue;
}
}
}
}
return -1;
}
}
三维插值
通过循环遍历实现
对x1、y1、z1对应key值B、H、Q,依次进行插值,得到最终插值结果。
public static double Insert_3d(double B, double H, double Q)
{
double[,,] arr = new double[3, 4, 4];
arr = new double[,,] { { { 52.3,53.1,53.9,54.7 },{ 54.9,55.7,56.6,57.4},{ 55.4,56.2,57,57.7},{ 56,56.7,57.5,58.3} },
{ { 50.8,51.6,52.4,53.2 },{ 53,53.8,54.6,55.4},{ 53.5,54.2,55,55.8},{ 54,54.7,55.5,56.2} },
{ { 49.7,50.6,51.4,52.2 },{ 51.7,52.5,53.4,54.2},{ 52.1,52.9,53.8,54.6},{ 52.6,53.4,54.2,55} } };
double[] xl = { 4, 6, 8, 10 };
double[] yl = { 5, 6, 7, 8 };
double[] zl = { 8, 10, 12 };
double[] x_values = new double[4];
double[] y_values = new double[4];
double[] z_values = new double[3];
double forecast = 0;
for (int k = 0; k < 3; k++)
{
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 4; i++)
{
x_values[i] = arr[k, j, i];
}
y_values[j] = InterAlgorithm.Compute(xl, x_values, B);
}
z_values[k] = InterAlgorithm.Compute(yl, y_values, H);
}
forecast = InterAlgorithm.Compute(zl, z_values, Q);
return forecast;
}
DeBug过程
最后
以上就是迷人大树为你收集整理的三维度双线性插值的全部内容,希望文章能够帮你解决三维度双线性插值所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复