📄 form1.cs
字号:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace 最小二乘拟合
{
public partial class Form1 : Form
{
int n = 0;
int linesNo = 1;
string name = null;
public Form1()
{
InitializeComponent();
}
public void 开始拟合ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (n == 0)
{
MessageBox.Show("请配置拟合次数!");
return;
}//判断拟合次数是否为0
if (name == null)
{
MessageBox.Show("请选择拟合数据!");
return ;
}//判断拟合数据是否为空
if (linesNo <(n+1))
{
MessageBox .Show ("拟合次数不得超过"+(linesNo -1)+"次,请重新设定!");
return ;
}
double[,] X=new double [linesNo ,n+1],
XT=new double [n+1,linesNo ],
XTX=new double [n+1,n+1],
XTX1=new double [n+1 ,n+1],
XTX1XT=new double [n+1,linesNo];
double[] x=new double [linesNo ],
b = new double[linesNo],
y = new double[linesNo];
StreamReader dataFile = new StreamReader(name );
linesNo = Int32 .Parse (dataFile.ReadLine());
for (int i = 0; i < linesNo; i++)
{
string temp = dataFile.ReadLine();
string[] str = System.Text.RegularExpressions.Regex.Split(temp , @"[\t]+");
x[i] =Convert .ToDouble ( str [0]) ;
//读取x[i]
y[i] =Convert .ToDouble (str [1] );
//读取y[i]
for (int j = 0; j < (n + 1); j++)
{
X[i, j] = Math.Pow(x[i], (double)j);
}//计算矩阵X
}
for (int i = 0; i < (n + 1); i++)
{
for (int j = 0; j < linesNo; j++)
{
XT[i, j] = X[j, i];
}
}//计算X的转置XT
for (int i = 0; i < (n + 1); i++)
{
for (int j = 0; j < (n + 1); j++)
{
for (int k = 0; k < linesNo ; k++)
{
XTX[i, j] += XT[i, k] * X[k, j];
}
}
}//计算XTX
double[,] newMatrix = XTX;
int[] T = new int[n+1];
double alpha = 0;
for (int k = 0; k < (n+1); k++)
{
double w = newMatrix[k, k];
int I = k;
T[k] = k;
for (int i = k + 1; i <(n+1); i++)
{
if (Math.Abs(newMatrix[i, k]) > Math.Abs(w))
{
w = newMatrix[i, k];
I = i;
}
}//选主元
if (w == 0)
{
MessageBox.Show("Singular!");
return;
}
if (I != k)
{
T[k] = I;
for (int j = 0; j < (n+1); j++)
{
double temp = newMatrix[k, j];
newMatrix[k, j] = newMatrix[I, j];
newMatrix[I, j] = temp;
}
}//行交换
alpha = 1 / newMatrix[k, k];
newMatrix[k, k] = alpha;
for (int i = 0; i < (n+1); i++)
{
if (i == k)
{
continue;
}
newMatrix[i, k] = (-1) * alpha * newMatrix[i, k];
}//计算第k列元素
for (int i = 0; i < (n+1); i++)
{
if (i == k)
{
continue;
}
for (int j = 0; j < (n+1); j++)
{
if (j == k)
{
continue;
}
newMatrix[i, j] += newMatrix[i, k] * newMatrix[k, j];
}
}//计算除第k列、k行以外其余元素
for (int j = 0; j < (n+1); j++)
{
if (j == k)
{
continue;
}
newMatrix[k, j] = alpha * newMatrix[k, j];
}//计算第k行其余元素
}
for (int k = n; k >= 0; k--)
{
if (T[k] != k)
{
int I = T[k];
for (int i = 0; i < (n+1); i++)
{
double temp = newMatrix[i, I];
newMatrix[i, I] = newMatrix[i, k];
newMatrix[i, k] = temp;
}
}
}//列交换
XTX1 = newMatrix;
//计算XTX的逆矩阵
for (int i = 0; i < (n + 1); i++)
{
for (int j = 0; j < linesNo; j++)
{
for (int k = 0; k < (n + 1); k++)
{
XTX1XT[i, j] += XTX1[i, k] * XT[k, j];
}
}
}//计算XTX的逆与XT的乘积
for (int i = 0; i < (n+1); i++)
{
for (int k = 0; k < linesNo; k++)
{
b[i] += XTX1XT[i, k] * y[k];
double temp = b[i] * x[i];
chart1.Series["拟合曲线"].Points.AddXY(x[i], temp);
chart1.Invalidate();
}
}//计算最小二乘解b[]
}//拟合过程
private void 使用方法ToolStripMenuItem_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("help.html");
}//打开帮助文件
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}//退出
private void 选择数据ToolStripMenuItem_Click(object sender, EventArgs e)
{
LabelX.Text = "X:";//显示X的条数
LabelY.Text = "Y:";//显示Y的条数
chart1.Series["原始曲线"].Points.Clear();//图形清空
openFileDialog1.ShowDialog();//打开文件
name = openFileDialog1.FileName;
if (openFileDialog1.FileName == "")
{
return;
}
if (!name.EndsWith(".txt"))
{
MessageBox.Show("数据格式为文本文件,请重新选择!");
return;
}//打开数据文件
//System.Diagnostics.Process.Start(openFileDialog1 .FileName );
dataGridView1.Rows.Clear();//数据清空
StreamReader dataFile = new StreamReader(name);
linesNo = Int32.Parse(dataFile.ReadLine());//记录条数
double[,] data = new double[linesNo, 2];
for (int i = 0; i < linesNo; i++)
{
string temp = dataFile.ReadLine();
string[] str = System.Text.RegularExpressions.Regex.Split(temp, @"[\t]+");
for (int j = 0; j < 2; j++)
{
data[i, j] = Convert.ToDouble(str[j]);
}
dataGridView1.Rows.Add(data[i, 0], data[i, 1]);//向DBview中添加记录
//chart1.Series.Clear();
//chart1.Invalidate();
chart1.Series["原始曲线"].Points.AddXY(data[i,0],data [i,1]);
chart1.Invalidate();//画图
}
LabelX.Text += linesNo;//显示新的X的条数
LabelY.Text += linesNo;//显示新的Y的条数
//读取数据并显示
}
private void 拟合次数ToolStripMenuItem_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.ShowDialog();//新窗体
n = Int32.Parse(f2.textBox1.Text);
}//读取拟合次数
private void 打开ToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog2.ShowDialog();
//string name=openFileDialog2 .FileName ;
try
{
System.Diagnostics.Process.Start(openFileDialog2.FileName);
}
catch (IOException)
{
MessageBox.Show("Error","无法打开文件!",MessageBoxButtons.OK,MessageBoxIcon .Error );
}
}
private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
{
saveFileDialog1.ShowDialog();
}
private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
{
dataGridView1.Rows.Clear();
chart1.Series["原始曲线"].Points.Clear();
chart1.Series["拟合曲线"].Points.Clear();
chart1.Invalidate();
}//数据,图像清空
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -