C# .Net Program to Find The Best Linearized Regression

For Two Variables

by Namir Shammas

The following program calculates the the best model and statistical coefficients for the following model:

H(Y) = A + B F(X)

Where X is the independent variable and Y is the dependent variable. In addition, H() and F() are transformation functions for the regression variables. The program also calculates the coefficient of determination R-Square.

The program performs different transformations on all the variables. These transformations include:

The program attempts to fit a total of 121 different curves. For data that have only positive values, the program succeeds in calculating 121 different models. The presence of negative values and zeros will reduce the number of models tested. The application skips certain transformations for an entire data set if ANY value is zero and/or negative. The bypass prevents run-time errors. Skipping a transformation for an entire data set makes the models easier to compare since they all are based on the same number of observations.

Click here to download a ZIP file containing the project files for this program.

The Application Form

The program is a Windows application that has the following interface:

The above interface has the following controls:

  1. The Read Data button invokes an Open File dialog box and allows you to select the file containing the data. Once you select a text-based data file, the application displays the contents in the Results text box.
  2. The Best Regression button performs the task of searching for the best fit. The program displays the results in the Results text box. These results consist of the source filename, the current date/time stamp, the number of observations used, and a sorted list of regression statistics. Each list member consists of the coefficient of determination, model equation, slope, and intercept. The program sorts the list in descending order based on the values of the coefficient of determination. Thus, the application displays the best fits first and the worst fits last. In case of input or calculation errors, the application displays and error message box.
  3. The Save Results button allows you to save the contents of the Results text box to a file. You can also use this button to save the source data to a different file, possible after editing that data.
  4. The Close button closes the application after prompting you for a confirmation.
  5. The Help button offers a message box containing a modest help text. The message box prompts you if you want to see sample data in the Results text box.
  6. The text boxes labeled ShiftX and ShiftY allow you to optionally specify shift values for the X and Y data, respectively. Left blank, the application uses the default value of 0.
  7. The text boxes labeled ScaleX and ScaleY allow you to optionally specify scale values for the X and Y data, respectively. Left blank, the application uses the default value of 1.
  8. The Results multi-line text box serves the following three purposes:
    1. The display of the source data and allowing you to edit that data. If you edit the data and then click the Best Regression button, the program asks you if you want to save the data in the source file, before proceeding with the calculations. If you click Yes, the program updates the data file and proceeds with the calculations. If you click No, the program proceeds with the calculations using the original data in the source file.
    2. The display of the results of the regression calculations.
    3. The display of sample data created by the application's help.

The Data File

The application reads data from text files. Each line in the source  text file may be one of the following:

Here is an example of a data file:

Sample Data file
Created 1/31/2006
General format for a data line is (the Weight value is optional):
X,Y[,Weight]
Next we have X = 100 and Y = 212
100,212
Notice leading spaces on next line
     10,50
The next line has a commented observation
! 33,45
25,77
Next data line has a weight value of 2 (X = 30, Y = 86, and weight = 2)
30,86,2 

The application allows for flexible commenting throughout the text file and is able to extract the data. You can  add leading characters like !, #, or % as the first character of a comment line. This option may make it easier for the human eye to spot comment lines. It may also make it easier for a separate utility program to strip the comment lines.

One reason clicking the Read Data button displays the data is to allow you to double check the integrity of the data. If a data line has only one value, then the application generates flags an error. If a data line has more than 3 values, the program ignores the extra values and does not raise an error.

Scaling and Shifting Values

The application shifts and scales data using the following formulas:

X' = ScaleX * (X - ShiftX)

Y' = ScaleY * (Y - ShiftY)

Keep the above equations in mind when you assign values for the shift and/or scale factors.

Offending Values?

Some of the mathematical transformations used take arguments that are only positive or only non-negative. In case you source data contains zeros and/or negative values, the application will avoid applying certain mathematical transformation to avoid causing run-time errors. Keep in mind that the program applies such avoidance to the entire data set and not just to those specific values that can cause error. You will notice the difference in the number of models display depending on your source data range. When using all-positive observations, the applications applies the entire set of transformations. When you have zeros or negative values, the application applies fewer transformations.

Here is a sample output:

The above output shows the first two best regression models. Here is the simple help message box:

The project file contains the following modules and classes of interest:

Here is the listing for class Form1:

using System.Diagnostics;
using System;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using Microsoft.VisualBasic;
using System.Data;
using System.Collections.Generic;
using System.IO;


namespace Best_XY_LR_cs
{
    public partial class Form1
    {
        public Form1()
        {
            InitializeComponent();
        }

        private string sDataFilename;
        private bool bEditMode;
        private bool bTextHasChanged;

        private void cmdCalc_Click(System.Object sender, System.EventArgs e)
        {
            CStatSum objLR;
            CResults objRes;
            int I;
            int nDataCOunt;
            double fShiftX;
            double fShiftY;
            double fScaleX;
            double fScaleY;
            string sBuffer;

            if (sDataFilename == "")
            {
                MessageBox.Show("Please select a data file first", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                return;
            }
            objLR = new CStatSum();
            objRes = new CResults();

            if (bTextHasChanged)
            {
                if (MessageBox.Show("Save changed data?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                {
                    File.WriteAllText(sDataFilename, txtRes.Text);
                }
                bTextHasChanged = false;
            }
            bEditMode = false;

            // check the Shift X text box
            if (txtShiftX.Text.Length > 0)
            {
                fShiftX = double.Parse(txtShiftX.Text);
            }
            else
            {
                fShiftX = 0;
            }

            // check the Shift Y text box
            if (txtShiftY.Text.Length > 0)
            {
                fShiftY = double.Parse(txtShiftY.Text);
            }
            else
            {
                fShiftY = 0;
            }

            // check the Scale X text box
            if (txtScaleX.Text.Length > 0)
            {
                fScaleX = double.Parse(txtScaleX.Text);
                if (fScaleX == 0)
                {
                    fScaleX = 1;
                }
            }
            else
            {
                fScaleX = 1;
            }

            // check the Scale Y text box
            if (txtScaleY.Text.Length > 0)
            {
                fScaleY = double.Parse(txtScaleY.Text);
                if (fScaleY == 0)
                {
                    fScaleY = 1;
                }
            }
            else
            {
                fScaleY = 1;
            }
            nDataCOunt = 0;
            if (objLR.GetData(sDataFilename, ref nDataCOunt, fShiftX, fShiftY, fScaleX, fScaleY))
            {
                Cursor = Cursors.WaitCursor;
                objLR.FindBestFit(ref objRes);
                objRes.SortResults();
                sBuffer = "";
                sBuffer = "Source Data File: " + sDataFilename + "\r\n" + "\r\n";
                sBuffer = sBuffer + "Date/Time: " + DateTime.Now + "\r\n" + "\r\n";
                sBuffer = sBuffer + "Nnmber of observations = " + nDataCOunt + "\r\n" + "\r\n";
                if (fScaleX != 1)
                {
                    sBuffer = sBuffer + "Scale X = " + fScaleX + "\r\n";
                }
                if (fShiftX != 0)
                {
                    sBuffer = sBuffer + "Shift X = " + fShiftX + "\r\n";
                }
                if (fScaleY != 1)
                {
                    sBuffer = sBuffer + "Scale Y = " + fScaleY + "\r\n";
                }
                if (fShiftY != 0)
                {
                    sBuffer = sBuffer + "Shift Y = " + fShiftY + "\r\n" + "\r\n";
                }
                for (I = 0; I <= objRes.Count() - 1; I++)
                {
                    sBuffer = sBuffer + "R-Sqr = " + objRes.GetR2(I).ToString() + "\r\n";
                    sBuffer = sBuffer + "Model: " + objRes.GetModel(I) + "\r\n";
                    sBuffer = sBuffer + "A  = " + objRes.GetIntercept(I).ToString() + ", B = " + objRes.GetSlope(I).ToString() + "\r\n";
                }
                txtRes.Text = sBuffer;
                sBuffer = "";
                Cursor = Cursors.Default;
                cmdSaveRes.Enabled = true;
            }
            else
            {
                MessageBox.Show("Error in processing data", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }


        }

        private void Form1_Load(System.Object sender, System.EventArgs e)
        {
            sDataFilename = "";
            cmdCalc.Enabled = false;
            cmdSaveRes.Enabled = false;
            bEditMode = false;
        }

        private void cmdReadData_Click(System.Object sender, System.EventArgs e)
        {
            dlgReadData.Filter = "All files (*.*)|*.*|Text files|*.txt|Data files (*.dat)|*.dat";
            if (dlgReadData.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                sDataFilename = dlgReadData.FileName;
                txtRes.Text = File.ReadAllText(sDataFilename);
                cmdCalc.Enabled = true;
                cmdSaveRes.Enabled = true;
                bTextHasChanged = false;
                bEditMode = true;
            }
        }

        private void cmdSaveRes_Click(System.Object sender, System.EventArgs e)
        {
            dlgSaveRes.Filter = "All files (*.*)|*.*|Text files|*.txt|Data files (*.dat)|*.dat";
            if (dlgSaveRes.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                File.WriteAllText(dlgSaveRes.FileName, txtRes.Text);
                bTextHasChanged = false;
            }
        }

        private void cmdClose_Click(System.Object sender, System.EventArgs e)
        {
            if (MessageBox.Show("Close application?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
            {
                Close();
            }
        }

        private void txtRes_TextChanged(System.Object sender, System.EventArgs e)
        {
            if (bEditMode)
            {
                bTextHasChanged = true;
            }
        }

        private void cmdHelp_Click(System.Object sender, System.EventArgs e)
        {
            string sText, s1, s2;
            double x1, x2;
            int i;
            Random r = new Random();

            sText = "Each line can be 1) empty, 2) a comment line or 3) a data line" + "\r\n" + "A data line has a pair of y and x values separated by a comma" + "\r\n" + "A data line can have a weight value that is appended after x and is separated by a comma" + "\r\n" + "Weights are optional and need to appear when their values are not 1" + "\r\n" + "A comment line must NOT start with any of the chatacters +-.0123456789" + "\r\n" + "Show an example?";
            if (MessageBox.Show(sText, "Help", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.Yes)
            {
                bEditMode = false;
                sText = "Sample data (example of free form comment line)" + "\r\n" + "45,32" + "\r\n" + "67,34" + "\r\n" + "Next line is an observation that is temporaryly commente dout" + "\r\n" + "! 56,23" + "\r\n";
                for (i = 1; i <= 10; i++)
                {
                    x1 = (int)(200 * r.NextDouble());
                    x2 = (int)(200 * r.NextDouble());
                    sText = sText + x1.ToString() + "," + x2.ToString() + "\r\n";
                }
                txtRes.Text = sText;
            }

        }
    }
}

Here is the listing for class CResults::

using System.Diagnostics;
using System;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using Microsoft.VisualBasic;
using System.Data;
using System.Collections.Generic;
using Microsoft.VisualBasic.CompilerServices;

namespace Best_XY_LR_cs
{
    public class CResults
    {

        private int m_nResCount;
        private TypeModule.ResType[] m_uResRec;

        public CResults()
        {
            m_nResCount = 0;
        }

        public void Add(string sModel, double fR2, double fSlope, double fIntercept, string sErr)
        {
            m_uResRec = (TypeModule.ResType[])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray((Array)m_uResRec, new TypeModule.ResType[m_nResCount + 1]);

            m_uResRec[m_nResCount].m_sModel = sModel;
            m_uResRec[m_nResCount].m_fR2 = fR2;
            m_uResRec[m_nResCount].m_fSlope = fSlope;
            m_uResRec[m_nResCount].m_fIntercept = fIntercept;
            m_uResRec[m_nResCount].m_sErr = sErr;
            m_nResCount++;
        }

        public void Clear()
        {
            m_nResCount = 0;
        }

        public int Count()
        {
            return m_nResCount;
        }

        public string GetModel(int nIndex)
        {
            return (nIndex > -1 && nIndex < m_nResCount ? (m_uResRec[nIndex].m_sModel) : "");
        }

        public double GetR2(int nIndex)
        {
            return (nIndex > -1 && nIndex < m_nResCount ? (m_uResRec[nIndex].m_fR2) : -1);
        }

        public double GetSlope(int nIndex)
        {
            return (nIndex > -1 && nIndex < m_nResCount ? (m_uResRec[nIndex].m_fSlope) : -1.0E+30);
        }

        public double GetIntercept(int nIndex)
        {
            return (nIndex > -1 && nIndex < m_nResCount ? (m_uResRec[nIndex].m_fIntercept) : -1.0E+30);
        }

        public string GetErr(int nIndex)
        {
            return (nIndex > -1 && nIndex < m_nResCount ? (m_uResRec[nIndex].m_sErr) : "");
        }

        public void SortResults()
        {
            bool bInorder;
            int I;
            int J;
            int N;
            int nOffset;
            int nResetCounter;
            TypeModule.ResType uBuffer;

            N = m_nResCount;
            nOffset = N;
            nResetCounter = 0;
            do
            {
                nOffset = (5 * nOffset) / 11;
                if (nOffset == 0)
                {
                    nOffset = 1;
                }
                bInorder = true;
                for (I = 0; I <= N - nOffset - 1; I++)
                {
                    J = I + nOffset;
                    if (m_uResRec[I].m_fR2 < m_uResRec[J].m_fR2)
                    {
                        uBuffer = m_uResRec[I];
                        m_uResRec[I] = m_uResRec[J];
                        m_uResRec[J] = uBuffer;
                        bInorder = false;
                    }
                }
                if (bInorder)
                {
                    nResetCounter++;
                }
                if ((!bInorder) && (nOffset == 1))
                {
                    nOffset = N;
                    for (I = 1; I <= nResetCounter; I++)
                    {
                        nOffset = (5 * nOffset) / 11;
                    }
                    if (nOffset == 0)
                    {
                        nOffset = 1;
                    }
                }
            } while (!(nOffset == 1 && bInorder));
        }
    }

}

Here is the listing for class CStatSum:

using System.Diagnostics;
using System;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using Microsoft.VisualBasic;
using System.Data;
using System.Collections.Generic;
using System.IO;
using Microsoft.VisualBasic.CompilerServices;


namespace Best_XY_LR_cs
{
    public class CStatSum
    {

        private const double EPSILON = 1.0e-20;
        private const string DIGIT_MARKERS = "-+0123456789.";

        private bool m_bZeroX;
        private bool m_bZeroY;
        private bool m_bNegX;
        private bool m_bNegY;

        private double m_fSum;
        private double m_fSumX;
        private double m_fSumX2;
        private double m_fSumY;
        private double m_fSumY2;
        private double m_fSumXY;
        private double m_fMeanX;
        private double m_fMeanY;
        private double m_fSdevX;
        private double m_fSdevY;
        private double m_fSlope;
        private double m_fIntercept;
        private double m_fR2;
        private string m_sTX;
        private string m_sTY;
        private string m_sWt;

        private double[] m_fX;
        private double[] m_fY;
        private double[] m_fWt;
        private double m_fShiftX;
        private double m_fShiftY;
        private double m_fScaleX;
        private double m_fScaleY;
        private int m_nDataCount;


        public void InitSums()
        {
            m_fSum = 0;
            m_fSumX = 0;
            m_fSumX2 = 0;
            m_fSumY = 0;
            m_fSumY2 = 0;
            m_fSumXY = 0;
        }

        public bool GetData(string sDataFilename, ref int nDataCount, double ShiftX, double ShiftY, double ScaleX, double ScaleY)
        {

            string sLine;
            string[] sLines;
            string[] sData;
            int I, J, K, N;
            bool bRes = true;
            char[] cDelim = new char[1];

            cDelim[0] = ',';
            try
            {
                sLines = File.ReadAllLines(sDataFilename);

                nDataCount = sLines.GetUpperBound(0);

                // Dimension arrays for maximum capacity
                m_fX = new double[nDataCount + 1];
                m_fY = new double[nDataCount + 1];
                m_fWt = new double[nDataCount + 1];

                J = 0;
                m_nDataCount = 0;
                while (!(J == sLines.Length))
                {
                    sLine = sLines[J].Trim(null);
                    // is line not empty?
                    if (sLine.Length > 0)
                    {
                        // is it NOT a comment?
                        if (DIGIT_MARKERS.IndexOf(sLine.Substring(0, 1)) >= 0)
                        {
                            sData = sLine.Split(cDelim);
                            N = sData.GetUpperBound(0);
                            m_fX[m_nDataCount] = double.Parse(sData[0]);
                            m_fY[m_nDataCount] = double.Parse(sData[1]);
                            if (N < 2)
                            {
                                m_fWt[m_nDataCount] = 1;
                            }
                            else
                            {
                                m_fWt[m_nDataCount] = double.Parse(sData[2]);
                            }
                            m_nDataCount++;
                        }
                    }
                    J++;
                }


                // adjust arrays to actual number of data
                m_fX = (double[])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray((Array)m_fX, new double[m_nDataCount + 1]);
                m_fY = (double[])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray((Array)m_fY, new double[m_nDataCount + 1]);
                m_fWt = (double[])Microsoft.VisualBasic.CompilerServices.Utils.CopyArray((Array)m_fWt, new double[m_nDataCount + 1]);
                nDataCount = m_nDataCount;

                for (I = 0; I <= m_nDataCount - 1; I++)
                {
                    m_fX[I] = ScaleX * (m_fX[I] - ShiftX);
                    m_fY[I] = ScaleY * (m_fY[I] - ShiftY);
                }

            }
            catch (Exception)
            {
                bRes = false;
            }

            return bRes;

        }

        public CStatSum()
        {
            InitSums();
        }

        private void Add(double X, double Y, double Wt)
        {
            m_fSum = m_fSum + Wt;
            m_fSumX = m_fSumX + X * Wt;
            m_fSumX2 = m_fSumX2 + X * X * Wt;
            m_fSumY = m_fSumY + Y * Wt;
            m_fSumY2 = m_fSumY2 + Y * Y * Wt;
            m_fSumXY = m_fSumXY + X * Y * Wt;
        }

        public void FindBestFit(ref CResults objRes)
        {

            int I;
            TypeModule.FitType ITX;
            TypeModule.FitType ITY;
            bool bOK;
            double fXt;
            double fYt;
            CErrors objErrs = new CErrors();

            if (m_nDataCount < 3)
            {
                return;
            }

            objRes.Clear();

            try
            {
                m_bZeroX = false;
                m_bZeroY = false;
                m_bNegX = false;
                m_bNegY = false;

                //objRes.Initialize

                for (I = 0; I <= m_nDataCount - 1; I++)
                {
                    if (m_fX[I] < 0)
                    {
                        m_bNegX = true;
                    }
                    if (m_fY[I] < 0)
                    {
                        m_bNegY = true;
                    }
                    if (Math.Abs(m_fX[I]) < EPSILON)
                    {
                        m_bZeroX = true;
                    }
                    if (Math.Abs(m_fY[I]) < EPSILON)
                    {
                        m_bZeroY = true;
                    }
                }

                m_sWt = "";

                for (ITY = TypeModule.FitType.eLinear; ITY <= TypeModule.FitType.eLn; ITY++)
                {
                    // validate transformations
                    if (m_bZeroY && m_bNegY)
                    {
                        bOK = CanHandleZeroAndNegative(ITY);
                    }
                    else if (m_bZeroY)
                    {
                        bOK = CanHandleZero(ITY);
                    }
                    else if (m_bNegY)
                    {
                        bOK = CanHandleNegative(ITY);
                    }
                    else
                    {
                        bOK = true;
                    }

                    // Can proceed?
                    if (bOK)
                    {

                        for (ITX = TypeModule.FitType.eLinear; ITX <= TypeModule.FitType.eLn; ITX++)
                        {

                            // validate transformations
                            if (m_bZeroX && m_bNegX)
                            {
                                bOK = CanHandleZeroAndNegative(ITX);
                            }
                            else if (m_bZeroX)
                            {
                                bOK = CanHandleZero(ITX);
                            }
                            else if (m_bNegX)
                            {
                                bOK = CanHandleNegative(ITX);
                            }
                            else
                            {
                                bOK = true;
                            }

                            // Can proceed?
                            if (bOK)
                            {

                                InitSums();

                                // store transformation data
                                m_sTX = SayTransform(ITX, "X");
                                m_sTY = SayTransform(ITY, "Y");

                                for (I = 0; I <= m_nDataCount - 1; I++)
                                {
                                    fXt = 0;
                                    fYt = 0;
                                    switch (ITX)
                                    {
                                        case TypeModule.FitType.eLinear:

                                            fXt = m_fX[I];
                                            break;
                                        case TypeModule.FitType.eSquare:

                                            fXt = Math.Pow(m_fX[I], 2);
                                            break;
                                        case TypeModule.FitType.eCube:

                                            fXt = Math.Pow(m_fX[I], 3);
                                            break;
                                        case TypeModule.FitType.eCubeRoot:

                                            fXt = Math.Pow(m_fX[I], (1.0 / 3.0));
                                            break;
                                        case TypeModule.FitType.eRecip:

                                            fXt = 1 / m_fX[I];
                                            break;
                                        case TypeModule.FitType.eRecipCubeRoot:

                                            fXt = 1 / Math.Pow(m_fX[I], (1.0 / 3.0));
                                            break;
                                        case TypeModule.FitType.eRecipSquare:

                                            fXt = 1 / Math.Pow(m_fX[I], 2);
                                            break;
                                        case TypeModule.FitType.eRecipCube:

                                            fXt = 1 / Math.Pow(m_fX[I], 3);
                                            break;
                                        case TypeModule.FitType.eSqrt:

                                            fXt = Math.Sqrt(m_fX[I]);
                                            break;
                                        case TypeModule.FitType.eRecipSqrt:

                                            fXt = 1 / Math.Sqrt(m_fX[I]);
                                            break;
                                        case TypeModule.FitType.eLn:

                                            fXt = Math.Log(m_fX[I]);
                                            break;
                                    }


                                    switch (ITY)
                                    {
                                        case TypeModule.FitType.eLinear:

                                            fYt = m_fY[I];
                                            break;
                                        case TypeModule.FitType.eSquare:

                                            fYt = Math.Pow(m_fY[I], 2);
                                            break;
                                        case TypeModule.FitType.eCube:

                                            fYt = Math.Pow(m_fY[I], 3);
                                            break;
                                        case TypeModule.FitType.eCubeRoot:

                                            fYt = Math.Pow(m_fY[I], (1.0 / 3.0));
                                            break;
                                        case TypeModule.FitType.eRecip:

                                            fYt = 1 / m_fY[I];
                                            break;
                                        case TypeModule.FitType.eRecipCubeRoot:

                                            fYt = 1 / Math.Pow(m_fY[I], (1.0 / 3.0));
                                            break;
                                        case TypeModule.FitType.eRecipSquare:

                                            fYt = 1 / Math.Pow(m_fY[I], 2);
                                            break;
                                        case TypeModule.FitType.eRecipCube:

                                            fYt = 1 / Math.Pow(m_fY[I], 3);
                                            break;
                                        case TypeModule.FitType.eSqrt:

                                            fYt = Math.Sqrt(m_fY[I]);
                                            break;
                                        case TypeModule.FitType.eRecipSqrt:

                                            fYt = 1 / Math.Sqrt(m_fY[I]);
                                            break;
                                        case TypeModule.FitType.eLn:

                                            fYt = Math.Log(m_fY[I]);
                                            break;
                                    }

                                    // add transformed data to statistical summations
                                    Add(fXt, fYt, m_fWt[I]);

                                }

                                objErrs.Clear();

                                // calculate regression statistics and store in
                                // object accessed by m_objRes
                                CalcLR(ref objErrs);

                                if (objErrs.GetCount() > 1)
                                {
                                    objRes.Add(m_sTY + " = A + B * " + m_sTX, m_fR2, m_fSlope, m_fIntercept, objErrs.GetErrText(0));
                                }
                                else
                                {
                                    objRes.Add(m_sTY + " = A + B * " + m_sTX, m_fR2, m_fSlope, m_fIntercept, "");
                                }

                            }

                        }

                    }
                }

            }
            catch (Exception ex)
            {
                objErrs.Add(ex.Message);
            }
        }



        private string SayTransform(TypeModule.FitType eVal, string sVar)
        {
            switch (eVal)
            {
                case TypeModule.FitType.eLinear:

                    return sVar;
                    break;
                case TypeModule.FitType.eSquare:
                    return sVar + "^2";
                    break;

                case TypeModule.FitType.eCube:
                    return sVar + "^3";
                    break;
                case TypeModule.FitType.eCubeRoot:
                    return sVar + "^1/3";
                    break;
                case TypeModule.FitType.eRecip:
                    return "1/" + sVar;
                    break;
                case TypeModule.FitType.eRecipCubeRoot:
                    return "1/" + sVar + "^1/3";
                    break;
                case TypeModule.FitType.eRecipSquare:
                    return "1/" + sVar + "^2";
                    break;
                case TypeModule.FitType.eRecipCube:
                    return "1/" + sVar + "^3";
                    break;
                case TypeModule.FitType.eSqrt:
                    return sVar + "^1/2";
                    break;
                case TypeModule.FitType.eRecipSqrt:
                    return "1/" + sVar + "^1/2";
                    break;
                case TypeModule.FitType.eLn:
                    return "Ln(" + sVar + ")";
                    break;
                default:
                    return "";
            }
        }


        private bool CanHandleZero(TypeModule.FitType eVal)
        {
            bool returnValue;

            switch (eVal)
            {
                case TypeModule.FitType.eLinear:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eSquare:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eCube:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eCubeRoot:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eSqrt:

                    returnValue = true;
                    break;
                default:

                    returnValue = false;
                    break;
            }
            return returnValue;
        }

        private bool CanHandleZeroAndNegative(TypeModule.FitType eVal)
        {
            bool returnValue;

            switch (eVal)
            {
                case TypeModule.FitType.eLinear:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eSquare:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eCube:

                    returnValue = true;
                    break;
                default:

                    returnValue = false;
                    break;
            }
            return returnValue;
        }

        private bool CanHandleNegative(TypeModule.FitType eVal)
        {
            bool returnValue;

            switch (eVal)
            {
                case TypeModule.FitType.eLinear:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eSquare:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eCube:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eRecip:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eRecipSquare:
                    returnValue = true;
                    break;

                case TypeModule.FitType.eRecipCube:

                    returnValue = true;
                    break;
                default:

                    returnValue = false;
                    break;
            }
            return returnValue;
        }


        private void CalcLR(ref CErrors objErrs)
        {

            if (m_fSum < 2)
            {
                return;
            }
            // caluclate regression
            try
            {
                m_fMeanX = m_fSumX / m_fSum;
                m_fMeanY = m_fSumY / m_fSum;
                m_fSdevX = Math.Sqrt((m_fSumX2 - Math.Pow(m_fSumX, 2) / m_fSum) / (m_fSum - 1));
                m_fSdevY = Math.Sqrt((m_fSumY2 - Math.Pow(m_fSumY, 2) / m_fSum) / (m_fSum - 1));
                m_fSlope = (m_fSum * m_fSumXY - m_fSumX * m_fSumY) / (m_fSum * m_fSumX2 - Math.Pow(m_fSumX, 2));
                m_fIntercept = m_fMeanY - m_fSlope * m_fMeanX;
                m_fR2 = Math.Pow(((m_fSum * m_fSumXY - m_fSumX * m_fSumY) / (m_fSum * (m_fSum - 1) * m_fSdevX * m_fSdevY)), 2);

            }
            catch (Exception ex)
            {
                objErrs.Add("For model" + m_sTY + " = A + B * " + m_sTX + "\r\n" + ex.Message);
            }

        }
    }

}

BACK

Copyright (c) Namir Shammas. All rights reserved.