5

スプレッドシートを模倣するために.netページを作成しています。シートにはこの式が含まれています

=ROUND(TREND(AA7:AE7,AA$4:AE$4,AF$4),1)

誰かがC#に相当するものを提供できますかTREND()?あるいは、誰かがその周りにショートカットを提供できれば、それも問題ありません。私はそこでの数学に精通していないので、もっと簡単な方法があるかどうかを知ることができません。

役立つ場合は、ここにいくつかのサンプル番号があります。

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

}
4

3 に答える 3

6

TRENDはExcel関数LINESTに基づいていると考えてください。このリンクhttps://support.office.com/en-us/article/LINEST-function-84d7d0d9-6e50-4101-977a-fa7abf772b6dをたどると、LINESTの背後にある機能が説明されます。

さらに、それが使用する基本式があります。

最初の式

2番目の式

于 2011-09-15T21:52:40.903 に答える
6

この投稿は、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);        
    }       
}

Pointは整数を使用して値を定義するため、アプリケーションでは小数点以下の桁数が多くなる可能性があるため、PointFを使用することを選択しました。このようなアルゴリズムの開発よりもコードの記述に多くの時間を費やしているため、数学の用語が間違っている場合はご容赦ください。ただし、どこかで用語を間違えた場合は、誰かに訂正してもらいたいと思います。

これは、Excel相互運用機能がバックグラウンドで読み込まれてブックのTrendメソッドを使用するのを待つよりも確かに高速です。

于 2013-05-23T18:40:34.837 に答える
0

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];
}
于 2019-12-18T08:28:44.757 に答える