如何重新创建在C#中调用TREND()的Excel公式?
我正在构建一个.net页面来模拟电子表格。该表包含此公式如何重新创建在C#中调用TREND()的Excel公式?,c#,excel,trend,C#,Excel,Trend,我正在构建一个.net页面来模拟电子表格。该表包含此公式 =ROUND(TREND(AA7:AE7,AA$4:AE$4,AF$4),1) 有人能提供相当于TREND()?或者,如果有人能提供一条捷径,也可以;我对那里的数学不够熟悉,不知道有没有更简单的方法 如果有帮助,这里有一些示例数字 AA7:AE7 68101214 或 10.213.617.520.423.8 AA$4:AE$4 600 800 1000 1200 1400 AF$4 650 编辑:这是我想到的,它似乎产生了与我的电子表
=ROUND(TREND(AA7:AE7,AA$4:AE$4,AF$4),1)
有人能提供相当于TREND()?或者,如果有人能提供一条捷径,也可以;我对那里的数学不够熟悉,不知道有没有更简单的方法
如果有帮助,这里有一些示例数字
AA7:AE7
68101214
或
10.213.617.520.423.8
AA$4:AE$4
600 800 1000 1200 1400
AF$4
650
编辑:这是我想到的,它似乎产生了与我的电子表格相同的数字
public static partial class Math2
{
public static double[] Trend(double[] known_y, double[] known_x, params double[] new_x)
{
// return array of new y values
double m, b;
Math2.LeastSquaresFitLinear(known_y, known_x, out m, out b);
List<double> new_y = new List<double>();
for (int j = 0; j < new_x.Length; j++)
{
double y = (m * new_x[j]) + b;
new_y.Add(y);
}
return new_y.ToArray();
}
// found at http://stackoverflow.com/questions/7437660/how-do-i-recreate-an-excel-formula-which-calls-trend-in-c
// with a few modifications
public static void LeastSquaresFitLinear(double[] known_y, double[] known_x, out double M, out double B)
{
if (known_y.Length != known_x.Length)
{
throw new ArgumentException("arrays are unequal lengths");
}
int numPoints = known_y.Length;
//Gives best fit of data to line Y = MC + B
double x1, y1, xy, x2, J;
x1 = y1 = xy = x2 = 0.0;
for (int i = 0; i < numPoints; i++)
{
x1 = x1 + known_x[i];
y1 = y1 + known_y[i];
xy = xy + known_x[i] * known_y[i];
x2 = x2 + known_x[i] * known_x[i];
}
M = B = 0;
J = ((double)numPoints * x2) - (x1 * x1);
if (J != 0.0)
{
M = (((double)numPoints * xy) - (x1 * y1)) / J;
//M = Math.Floor(1.0E3 * M + 0.5) / 1.0E3; // TODO this is disabled as it seems to product results different than excel
B = ((y1 * x2) - (x1 * xy)) / J;
// B = Math.Floor(1.0E3 * B + 0.5) / 1.0E3; // TODO assuming this is the same as above
}
}
}
公共静态部分类Math2
{
公共静态双[]趋势(双[]已知y,双[]已知x,参数双[]新x)
{
//返回新y值的数组
双m,b;
数学2.租赁方线性(已知y、已知x、out m、out b);
List new_y=新列表();
对于(int j=0;j
考虑趋势是基于Excel函数LINEST的。
如果您遵循此链接,它将解释LINEST背后的功能
此外,您还可以找到它使用的基本公式
这篇文章非常有用,因为我们需要在C#中重新创建这篇文章。感谢Jeff的上述回答,我使用以下公式重新创建了该公式:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
public static class MathHelper
{
/// <summary>
/// Gets the value at a given X using the line of best fit (Least Square Method) to determine the equation
/// </summary>
/// <param name="points">Points to calculate the value from</param>
/// <param name="x">Function input</param>
/// <returns>Value at X in the given points</returns>
public static float LeastSquaresValueAtX(List<PointF> points, float x)
{
float slope = SlopeOfPoints(points);
float yIntercept = YInterceptOfPoints(points, slope);
return (slope * x) + yIntercept;
}
/// <summary>
/// Gets the slope for a set of points using the formula:
/// m = ∑ (x-AVG(x)(y-AVG(y)) / ∑ (x-AVG(x))²
/// </summary>
/// <param name="points">Points to calculate the Slope from</param>
/// <returns>SlopeOfPoints</returns>
private static float SlopeOfPoints(List<PointF> points)
{
float xBar = points.Average(p => p.X);
float yBar = points.Average(p => p.Y);
float dividend = points.Sum(p => (p.X - xBar) * (p.Y - yBar));
float divisor = (float)points.Sum(p => Math.Pow(p.X - xBar, 2));
return dividend / divisor;
}
/// <summary>
/// Gets the Y-Intercept for a set of points using the formula:
/// b = AVG(y) - m( AVG(x) )
/// </summary>
/// <param name="points">Points to calculate the intercept from</param>
/// <returns>Y-Intercept</returns>
private static float YInterceptOfPoints(List<PointF> points, float slope)
{
float xBar = points.Average(p => p.X);
float yBar = points.Average(p => p.Y);
return yBar - (slope * xBar);
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统图;
公共静态类MathHelper
{
///
///使用最佳拟合线(最小二乘法)获取给定X处的值,以确定方程
///
///从中计算值的点
///函数输入
///给定点X处的值
公共静态浮动租赁方形值ATX(列表点,浮动x)
{
浮动坡度=坡度点(点);
浮动yIntercept=YInterceptOfPoints(点,斜率);
返回(斜率*x)+yIntercept;
}
///
///使用以下公式获取一组点的坡度:
///m=∑ (x-AVG(x)(y-AVG(y))/∑ (x-平均值(x))²
///
///从中计算坡度的点
///坡度点
专用静态浮动斜率点(列表点)
{
浮动xBar=点数。平均值(p=>p.X);
浮动yBar=点数。平均值(p=>p.Y);
浮动股息=点数总和(p=>(p.X-xBar)*(p.Y-yBar));
浮点除数=(float)points.Sum(p=>Math.Pow(p.X-xBar,2));
回报股息/除数;
}
///
///使用以下公式获取一组点的Y截距:
///b=平均值(y)-m(平均值(x))
///
///要从中计算截距的点
///Y截距
专用静态浮动YInterceptOfPoints(列表点、浮动斜率)
{
浮动xBar=点数。平均值(p=>p.X);
浮动yBar=点数。平均值(p=>p.Y);
返回yBar-(斜率*xBar);
}
}
由于Point使用整数定义其值,因此我选择使用PointF,因为在我们的应用程序中,小数点可以有很多位。请原谅我使用的任何数学术语,因为我花在编写代码上的时间比开发类似算法的时间要多,尽管如果我在某个地方误判了一个术语,我希望任何人都能纠正我的错误
这当然比等待Excel Interop在后台加载以使用工作簿的趋势方法要快。感谢用javascript重新创建的代码
function LeastSquaresFitLinear(known_y, known_x, offset_x)
{
if (known_y.length != known_x.length) return false; //("arrays are unequal lengths");
var numPoints = known_y.length;
var x1=0, y1=0, xy=0, x2=0, J, M, B;
for (var i = 0; i < numPoints; i++)
{
known_x[i] -= offset_x;
x1 = x1 + known_x[i];
y1 = y1 + known_y[i];
xy = xy + known_x[i] * known_y[i];
x2 = x2 + known_x[i] * known_x[i];
}
J = (numPoints * x2) - (x1 * x1);
if (J != 0.0)
{
M = ((numPoints * xy) - (x1 * y1)) / J;
B = ((y1 * x2) - (x1 * xy)) / J;
}
return [M,B];
}
函数LeastSquaresFitLinear(已知y、已知x、偏移x)
{
if(known_y.length!=known_x.length)返回false;//(“数组长度不等”);
var numPoints=已知长度;
变量x1=0,y1=0,xy=0,x2=0,J,M,B;
对于(变量i=0;i
我找到了一个最小平方拟合函数,它取一组{x,y}然后返回M和B。然后我可以使用M和B以及一组新的x值来生成y值,作为趋势结果返回。这些都正确吗?老实说,我对LINEST或trend函数不太熟悉。使用这些函数时会发生很多事情,从文档中看,它们似乎有点不可靠(垃圾)