3

我正在尝试使用 C# 应用程序分析一些数据,并且需要计算趋势线。我知道趋势线有多种类型,但现在我正在尝试计算指数增长;我将使用它来预测未来的价值。我一直在研究的方程式是

x(t) = x(0) * ((1+r)^t)

这是我为尝试复制图形而编写的代码:

public void ExponentialBestFit(List<DateTime> xvalues, List<double> yvalues)

        {
            //Find the first value of y (The start value) and the first value of x (The start date)
            xzero = Convert.ToDouble(xvalues[0].ToOADate());
            yzero = yvalues[0];
            if (yzero == 0)
                yzero += 0.1;

            //For every value of x (exluding the 1st value) find the r value
            //
            //                       |   y   |          Where t = the time sinse the start time (time period)
            //Equation for r = t root|-------| - 1      Where y = the current y value
            //                       |  y[0] |          Where y[0] = the first y value  #IMPROVMENT - Average 1st y value in range
            //
            double r = 0;

            //c is a count of how many r values are added; it is not equal to the count of all the values
            int c = 0;
            for (int i = 1; i < xvalues.Count; i++)
            {
                r += Math.Pow(yvalues[i]/yzero, 1/(Convert.ToDouble(xvalues[i].ToOADate()) - xzero)) - 1;
                c++;
            }

            r = r / c;           
        }

我传入的数据是一段时间内的,但是时间增加的增量并不相同。当我在 excel 中创建图表时,他们使用不同的公式

x(t) = x(0)*(e^kt)

但是我想我不知道 k 值是从哪里生成的。我传入的两个列表是日期和值,每个列表中的每一行对应于另一个列表中的同一行。问题是 - 有没有更好的方法来创建方程和变量,我得到的变量对于我的数据来说是最准确的吗?

4

3 回答 3

3

这是提供的 javascript 的 c# 版本。

    IEnumerable<double> Growth(IList<double> knownY, IList<double> knownX, IList<double> newX, bool useConst)
    {
        // Credits: Ilmari Karonen

        // Default values for optional parameters:
        if (knownY == null) return null;
        if (knownX == null)
        {
            knownX = new List<double>();
            for (var i  = 0; i<=knownY.Count; i++)
                knownX.Add(i++);
        }
        if (newX == null)
        {
            newX = new List<double>();
            for (var i = 0; i <= knownY.Count; i++)
                newX.Add(i++);
        }

        int n = knownY.Count;
        double avg_x = 0.0;
        double avg_y = 0.0;
        double avg_xy = 0.0;
        double avg_xx = 0.0;
        double beta = 0.0;
        double alpha = 0.0;
        for (var i = 0; i < n; i++)
        {
            var x = knownX[i];
            var y = Math.Log(knownY[i]);
            avg_x += x;
            avg_y += y;
            avg_xy += x * y;
            avg_xx += x * x;
        }
        avg_x /= n;
        avg_y /= n;
        avg_xy /= n;
        avg_xx /= n;

        // Compute linear regression coefficients:
        if (useConst)
        {
            beta = (avg_xy - avg_x * avg_y) / (avg_xx - avg_x * avg_x);
            alpha = avg_y - beta * avg_x;
        }
        else
        {
            beta = avg_xy / avg_xx;
            alpha = 0.0;
        }

        // Compute and return result array:
        return newX.Select(t => Math.Exp(alpha + beta*t)).ToList();

    }
于 2013-01-25T15:54:27.567 回答
1

以下 JavaScript 代码应该会有所帮助。我用它来实现 Excel 的GROWTH函数。它是用 JavaScript 编写的,但将其移植到 C# 应该很容易。请注意,其中大部分是由其他人编写的(代码中的学分)。

function GROWTH(known_y, known_x, new_x, use_const) {
  // Credits: Ilmari Karonen

  // Default values for optional parameters:
  if (typeof(known_x) == 'undefined') {
    known_x = [];
    for (var i = 1; i <= known_y.length; i++) known_x.push(i);
  }
  if (typeof(new_x) == 'undefined') {
    new_x = [];
    for (var i = 1; i <= known_y.length; i++) new_x.push(i);
  }
  if (typeof(use_const) == 'undefined') use_const = true;

  // Calculate sums over the data:
  var n = known_y.length;
  var avg_x = 0;
  var avg_y = 0;
  var avg_xy = 0;
  var avg_xx = 0; 
  for (var i = 0; i < n; i++) {
    var x = known_x[i];
    var y = Math.log(known_y[i]);
    avg_x += x;
    avg_y += y;
    avg_xy += x*y;
    avg_xx += x*x;
  }
  avg_x /= n;
  avg_y /= n;
  avg_xy /= n;
  avg_xx /= n;

  // Compute linear regression coefficients:
  if (use_const) {
    var beta = (avg_xy - avg_x*avg_y) / (avg_xx - avg_x*avg_x);
    var alpha = avg_y - beta*avg_x;
  } else {
    var beta = avg_xy / avg_xx;
    var alpha = 0;
  }

  // Compute and return result array:
  var new_y = [];
  for (var i = 0; i < new_x.length; i++) {
    new_y.push(Math.exp(alpha + beta * new_x[i]));
  }
  return new_y;
}
于 2013-01-25T14:13:05.497 回答
0

因为x(t)=x(0)*e^{kt},我们可以取对数来得到ln x(t)=ln x(0) + kt。这意味着要找到ln x(0)k,您可以找到适合数据的最小二乘{(t,ln x(t))}。这会告诉你那个ln x(t) = b + at,所以那个k=ax(0)=e^b

于 2014-05-12T15:53:26.930 回答