如何在 C# 中重新创建调用 TREND() 的 Excel 公式?
我正在构建一个 .net 页面来模仿电子表格。该工作表包含此公式
=ROUND(TREND(AA7:AE7,AA$4:AE$4,AF$4),1)
有人可以提供与 TREND()
等效的 C# 公式吗?或者,如果任何人都可以提供围绕它的快捷方式,那也很好;我对那里的数学不太熟悉,不知道是否有更简单的方法。
如果有帮助的话,这里有一些示例数字。
AA7:AE7 6 8 10 12 14
或 10.2 13.6 17.5 20.4 23.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
}
}
}
I'm building a .net page to mimic a spreadsheet. The sheet contains this formula
=ROUND(TREND(AA7:AE7,AA$4:AE$4,AF$4),1)
Can someone provide the C# equivalent of TREND()
? Alternatively if anyone can provide a shortcut around it that's fine too; I'm not familiar enough with the math there to know if there's an easier way.
Here are some sample numbers if it helps.
AA7:AE76 8 10 12 14
or10.2 13.6 17.5 20.4 23.8
AA$4:AE$4600 800 1000 1200 1400
AF$4650
edit: here's what I came up with and it seems to be producing the same numbers as my spreadsheet.
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
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
考虑 TREND 基于 Excel 函数 LINEST。
如果您点击此链接,https://support.office.com/en-us/article/LINEST-function-84d7d0d9-6e50-4101-977a-fa7abf772b6d,它将解释 LINEST 背后的功能。
此外,您还会找到它使用的基本公式。
。
Consider TREND is based upon the Excel Function, LINEST.
If you follow this link, https://support.office.com/en-us/article/LINEST-function-84d7d0d9-6e50-4101-977a-fa7abf772b6d, it will explain the functionality behind LINEST.
In addition, you'll find the base formula that it uses.
.
这篇文章非常有帮助,因为我们需要在 C# 中重新创建它。感谢上面 Jeff 的回答,我使用以下内容重新创建了该公式:
由于 Point 使用整数来定义其值,因此我选择使用 PointF,因为在我们的应用程序中,可以有很多小数位。请原谅任何数学术语,因为我花更多的时间编写代码而不是开发这样的算法,尽管如果我在某个地方弄错了一个术语,我希望有人纠正我。
这肯定比等待 Excel Interop 在后台加载以使用工作簿的趋势方法要快。
This post has been very helpful as we've needed to recreate this in C#. Thanks to Jeff's answer above I've recreated that formula using the following:
Since Point uses Integers to define its values I've elected to use PointF since in our applications, there can be many decimal places. Pardon any math terminology that is off as I spend more time writing code than developing algorithms like this although I'd love anyone to correct me should I have mistated a term somewhere.
This is certainly faster than waiting for Excel Interop to load up in the background to use the workbook's Trend method.
感谢您用 JavaScript 重新创建的代码。
Thanks for the code, recreated in javascript.