工程计算实验代码:

实验一:


实验二:

#include <iostream>

using namespace std;

//调试用, 增加更多的输出 
//#define DEBUG

void Output1D(double matrix[], int row);

int main() {
	int n = 0;
	while(n<15) {
		n++;
		printf(
		    "-------------------------------------------------\n"
		    "第%d次循环:  n=%d\n"
		    "\n",n,n);
//		scanf("%d", &n);
		double H[n][n] = { 0 };
		double b[n]= {0};
		double l[n][n]= {0};
		double d[n]= {0};
		double y[n]= {0};
		double x[n]= {0};

		//初始化希尔伯特矩阵H
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				H[i][j] = 1.0 / (i + 1 + j + 1 - 1);
			}
		}
#ifdef DEBUG
		//输出h:
		printf("H:\n");
		for(int i=0; i<n; ++i) {
			Output1D(H[i],n);
			putchar('\n');
		}
		putchar('\n');
		putchar('\n');
#endif
		//求得矩阵b
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				b[i] += H[i][j];
			}
		}
#ifdef DEBUG
		//输出b
		printf("b:\n");
		Output1D(b,n);
		putchar('\n');
		putchar('\n');
#endif

		//初始化矩阵l
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++) {
				l[i][j]=0;
			}
		}
		for (int i = 0; i < n; ++i) {
			l[i][i]=1;
		}
#ifdef DEBUG
		//输出l:
		printf("L:\n");
		for(int i=0; i<n; ++i) {
			Output1D(l[i],n);
			putchar('\n');
		}
		putchar('\n');
#endif

		//对希尔伯特矩阵H进行分解
		//H=LDL(T)
		int row =n;
		for (int k = 0; k < row; ++k) {
			d[k] = H[k][k];
			for (int i = 0; i < k; ++i) {
				d[k] -= l[k][i] * l[k][i] * d[i];
			}
			for (int i = k + 1; i < row; ++i) {
				double temp = H[k][i];
				for (int j = 0; j < k; ++j) {
					temp -= l[k][j] * d[j] * l[i][j];
				}
				l[i][k] = temp / (l[k][k] * d[k]);
			}
		}
#ifdef DEBUG
		//输出d:
		printf("D:\n");
		Output1D(d,n);
		putchar('\n');
		putchar('\n');
#endif

#ifdef DEBUG
		//输出l
		printf("L:\n");
		for(int i=0; i<n; ++i) {
			Output1D(l[i],n);
			putchar('\n');
		}
		putchar('\n');
#endif

		//对向量y进行求解
		//Ly=b
		y[0] = b[0];
		for (int i = 1; i < row; ++i) {
			y[i] = b[i];
			for (int k = 0; k < i; ++k) {
				y[i] -= l[i][k] * y[k];
			}
		}
		//输出y:
		printf("Y:\n");
		Output1D(y,n);
		putchar('\n');
		putchar('\n');

		//对向量x进行求解
		//L(t)x=y
		x[row - 1] = y[row - 1] / d[row - 1];
		for (int i = row - 2; i >= 0; --i) {
			x[i] = y[i] / d[i];
			for (int k = i + 1; k < row; ++k) {
				x[i] -= l[k][i] * x[k];
			}
		}
		//输出x:
		printf("X:\n");
		Output1D(x,n);
		putchar('\n');
		putchar('\n');

		//计算剩余向量
		//r=b-Hx
		double r[n]= {0};
		double temp=0;
		for(int i=0; i<n; i++) {
			temp=0;
			for(int j=0; j<n; ++j) {
				temp+=H[i][j]*x[j];
			}
			r[i]=b[i]-temp;
		}
		//输出r:
		printf("r:\n");
		Output1D(r,n);
		putchar('\n');
		putchar('\n');

		//计算与x=(1,1, ... ,1)T 的差值
		//diff_x=x'-x
		double diff_x[n]= {0};
		for(int i=0; i<n; ++i) {
			diff_x[i]=x[i]-1;
		}
		//输出diff_x:
		printf("diff_x:\n");
		Output1D(diff_x,n);
		putchar('\n');
		putchar('\n');

	}
	return 0;
}

void Output1D(double matrix[], int n) {
	for (int i = 0; i < n; ++i) {
		printf("%.8lf ", matrix[i]);
	}
	return;
}

实验三:

源码:

Jacobi:

#include <iostream>
#include <cmath>
#include <cstring>

//#define DEBUG		//DEBUG用, 增加更多的输出
#define PRO_1		//第一题时需要定义


using namespace std;

const int N=30;
const int INF=10000;

void iniA(double a[N][N], int n) ;
void iniB(double b[N],int n);
void input1D(double vec[N], int n) ;
void input2D(double matrix[N][N],int n);
void output1D(double vec[N],int n);
void output2D(double matrix[N][N], int n);
void VectorMinus(double a[N],double b[N],double ans[N],int n);
void MatrixMtimes(double a[N][N], double b[N][N],double ans[N][N],int n) ;
void VectorCopy(double src[N],double dst[N],int n);
void MatrixCopy(double src[N][N],double dst[N][N],int n) ;
double Norm2(double a[N],int n) ;


int main(int argc, char* argv[]) {

	double ma0[N][N]= {0};
	double coefficientB[N]= {0};
	double x_k1[N]= {0};
	double x_k0[N]= {0};
	double x_diff[N]= {0};
	double eps=0.0;

//------------------------------------
//第一题:
#ifdef PRO_1
	//默认矩阵为方阵
	int row=0;
	printf(
	    "输入矩阵的行列:\n"
	    "row = column =  ");
	scanf("%d",&row);

	printf("输入矩阵A:\n");
	input2D(ma0,row);

	printf("输入系数矩阵B:\n");
	input1D(coefficientB,row);


	printf("输入初始X0 = ");
	for(int i=0; i<row; ++i) {
		scanf("%lf",&x_k0[i]);
	}

	printf("输入终止条件: eps = ");
	scanf("%lf",&eps);

	int k=0;
	bool isDiverge=0;
	do {

#ifdef DEBUG
		printf(
		    "第%d次循环\n"
		    "X_k0=\n"
		    ,k);
		output1D(x_k0,row);
#endif
		for(int i=0; i<row; ++i) {
			double sum=0.0;
			for(int j=0; j<row; ++j) {
				sum+=ma0[i][j]*x_k0[j];
			}
			sum-=ma0[i][i]*x_k0[i];
			sum-=coefficientB[i];
			sum/=(-ma0[i][i]);
			x_k1[i]=sum;
		}
		double tempAns[N]= {0};
		VectorMinus(x_k1,x_k0,tempAns,row);
		VectorCopy(tempAns,x_diff,row);
		VectorCopy(x_k1,x_k0,row);
#ifdef DEBUG
		printf("x_diff=\n");
		output1D(x_diff,row);
		printf(
		    "x_diff的2范数 = \n"
		    "%14.10lf\n"
		    ,Norm2(x_diff,row));
#endif

		//当Jacobi的结果超过既定的最大值INF时, 判定为Jacobi发散:
		for(int i=0; i<row; ++i) {
			if(fabs(x_k1[i])>=INF) {
				isDiverge=true;
				break;
			}
		}
		if(isDiverge) {
			break;
		}
	} while(Norm2(x_diff,row)>=eps);


	if(isDiverge) {
		isDiverge=false;
		printf("Jacobi发散....\n");
	} else {
		printf("最终结果: x_k1=\n");
		output1D(x_k1,row);
	}

///--------------------------------------------------
//第二题:
#else
	int ROW=0, row=0;
	printf("输入方阵的最大行数: ROW = ");
	scanf("%d",&ROW);
	while(row<ROW) {
		++row;
		printf("row = %d\n",row);
		iniA(ma0,row);
		iniB(coefficientB,row);
		eps=0.000001;

#ifdef DEBUG
		printf("矩阵A:\n");
		output2D(ma0,row);
		printf("系数矩阵B:\n");
		output1D(coefficientB,row);
#endif

		int k=0;
		const int DIVERGE=100;
		bool isDiverge=0;
		do {
			//当迭代次数>DIVERGE时判定为发散
			if(++k>DIVERGE) {
				isDiverge=true;
				break;
			}

#ifdef DEBUG
			printf(
			    "第%d次循环\n"
			    "X_k0=\n"
			    ,k);
			output1D(x_k0,row);
#endif
			for(int i=0; i<row; ++i) {
				double sum=0.0;
				for(int j=0; j<row; ++j) {
					sum+=ma0[i][j]*x_k0[j];
				}
				sum-=ma0[i][i]*x_k0[i];
				sum-=coefficientB[i];
				sum/=(-ma0[i][i]);
				x_k1[i]=sum;
			}
			double tempAns[N]= {0};
			VectorMinus(x_k1,x_k0,tempAns,row);
			VectorCopy(tempAns,x_diff,row);
			VectorCopy(x_k1,x_k0,row);
#ifdef DEBUG
			printf("x_diff=\n");
			output1D(x_diff,row);
			printf(
			    "x_diff的2范数 = \n"
			    "%14.10lf\n"
			    ,Norm2(x_diff,row));
#endif


			//当Jacobi的结果超过既定的最大值INF时, 判定为Jacobi发散:
			for(int i=0; i<row; ++i) {
				if(fabs(x_k1[i])>=INF) {
					isDiverge=true;
					break;
				}
			}
			if(isDiverge) {
				break;
			}
		} while(Norm2(x_diff,row)>=eps);

		if(isDiverge) {
			isDiverge=false;
			printf("Jacobi发散....\n");
		} else {
			printf(
			    "最终结果: \n"
			    "经过%d次迭代\n"
			    "最终结果: x_k1=\n"
			    ,k);
			output1D(x_k1,row);
		}
	}

#endif

	return 0;
}

//向量减法:
void VectorMinus(double a[N],double b[N],double ans[N],int n) {
	const double MINIMUM=pow(10,-11);
	for(int i=0; i<n; ++i) {
		ans[i]=a[i]-b[i];
		if(ans[i]<MINIMUM) {
			ans[i]=0;
		}
	}
	return ;
}

//方阵乘法:
void MatrixMtimes(double a[N][N], double b[N][N],double ans[N][N],int n) {
	const double MINIMUM=pow(10,-11);
	memset(ans,0,sizeof(double)*N*N);
	for(int i=0; i<n; ++i) {
		for(int j=0; j<n; ++j) {
			for(int k=0; k<n; ++k) {
				ans[i][j]+=a[i][k]*b[k][j];
			}
			//当值小于10^-11时, 视为=0
			if(ans[i][j]<=MINIMUM) {
				ans[i][j]=0;
			}
		}
	}
	return ;
}

//向量复制:
void VectorCopy(double src[N],double dst[N],int n) {
	for(int i=0; i<n; ++i) {
		dst[i]=src[i];
	}
	return ;
}


//求向量的2范数:
double Norm2(double a[N],int n) {
	double sum=0.0;
	for(int i=0; i<n; ++i) {
		sum+=fabs(a[i]*a[i]);
	}
	return sqrt(sum);
}


void iniA(double a[N][N], int n) {
	for(int i=0; i<n; ++i) {
		for(int j=0; j<n; ++j) {
			a[i][j]= 1.0/(i+j+1);
		}
	}
	return ;
}

void iniB(double b[N],int n) {
	double sum=0;
	for(int i=0; i<n; ++i) {
		sum=0;
		for(int j=0; j<n; ++j) {
			sum+=1.0/(i+j+1);
		}
		b[i]=sum;
	}
	return ;
}

void input1D(double vec[N], int n) {
	for(int i=0; i<n; ++i) {
		scanf("%lf",&vec[i]);
	}
	return ;
}

void input2D(double matrix[N][N],int n) {
	for(int i=0; i<n; ++i) {
		input1D(matrix[i],n);
	}
	return ;
}

void output1D(double vec[N],int n) {
	for(int i=0; i<n; ++i) {
		printf("%+18.10lf ",vec[i]);
	}
	putchar('\n');
	return ;
}

void output2D(double matrix[N][N], int n) {
	for(int i=0; i<n; ++i) {
		output1D(matrix[i],n);
	}
	putchar('\n');
	return ;
}



SOR:

#include <iostream>
#include <cmath>
#include <cstring>

//#define DEBUG		//DEBUG用, 增加更多的输出
//#define PRO_1		//第一题时需要定义


using namespace std;

const int N=30;
const int INF=10000;

void iniA(double a[N][N], int n) ;
void iniB(double b[N],int n);
void input1D(double vec[N], int n) ;
void input2D(double matrix[N][N],int n);
void output1D(double vec[N],int n);
void output2D(double matrix[N][N], int n);
void VectorMinus(double a[N],double b[N],double ans[N],int n);
void VectorCopy(double src[N],double dst[N],int n);
double Norm2(double a[N],int n) ;

int main(void) {

	double ma0[N][N]= {0};
	double coefficientB[N]= {0};
	double x_k1[N]= {0};
	double x_k0[N]= {0};
	double x_diff[N]= {0};
	double eps=0.0;
	double omega=0.0;

//----------------------------------------
//第一题:
#ifdef PRO_1
	//默认矩阵为方阵
	int row=0;
	printf(
	    "输入矩阵的行列:\n"
	    "row = column =  ");
	scanf("%d",&row);

	printf("输入矩阵A:\n");
	input2D(ma0,row);

	printf("输入系数矩阵B:\n");
	input1D(coefficientB,row);


	printf("输入初始X0 = ");
	for(int i=0; i<row; ++i) {
		scanf("%lf",&x_k0[i]);
	}

	printf("输入终止条件: eps = ");
	scanf("%lf",&eps);

	printf("输入松弛因子: omega = ");
	scanf("%lf",&omega);

	int k=0;
	bool isDiverge=0;

	do {

#ifdef DEBUG
		printf(
		    "第%d次循环\n"
		    "X_k0=\n"
		    ,k);
		output1D(x_k0,row);
#endif

		for(int i=0; i<row; ++i) {
			double sum=0.0;
			for(int j=0; j<i; ++j) {
				sum-=ma0[i][j]*x_k1[j];
			}
			for(int j=i; j<row; ++j) {
				sum-=ma0[i][j]*x_k0[j];
			}
			sum+=coefficientB[i];
			sum*=omega;
			sum/=ma0[i][i];
			sum+=x_k0[i];
			x_k1[i]=sum;
		}
		VectorMinus(x_k1,x_k0,x_diff,row);
		VectorCopy(x_k1,x_k0,row);
#ifdef DEBUG
		printf("x_k1=\n");
		output1D(x_k1,row);
		printf("x_diff=\n");
		output1D(x_diff,row);
		printf(
		    "x_diff的2范数 = \n"
		    "%14.10lf\n"
		    ,Norm2(x_diff,row));
#endif

		//当SOR的结果超过既定的最大值INF时, 判定为发散:
		for(int i=0; i<row; ++i) {
			if(fabs(x_k1[i])>=INF) {
				isDiverge=true;
				break;
			}
		}
		if(isDiverge) {
			break;
		}
	} while(Norm2(x_diff,row)>=eps);
	if(isDiverge) {
		isDiverge=false;
		printf("SOR发散....\n");
	} else {
		printf(
		    "最终结果: \n"
		    "经过%d次迭代\n"
		    "最终结果: x_k1=\n"
		    ,k);
		output1D(x_k1,row);
	}
//----------------------------------------
//第二题:
#else
	int ROW=0, row=0;
	printf("输入方阵的最大行数: ROW = ");
	scanf("%d",&ROW);
	printf("输入松弛因子: omega = ");
	scanf("%lf",&omega);
	while(row<ROW) {
		++row;
		printf("row = %d\n",row);
		iniA(ma0,row);
		iniB(coefficientB,row);
		eps=0.000001;

#ifdef DEBUG
		printf("矩阵A:\n");
		output2D(ma0,row);
		printf("系数矩阵B:\n");
		output1D(coefficientB,row);
#endif

		int k=0;
		bool isDiverge=false;

		do {
			k++;


#ifdef DEBUG
			printf(
			    "第%d次循环\n"
			    "X_k0=\n"
			    ,k);
			output1D(x_k0,row);
#endif

			for(int i=0; i<row; ++i) {
				double sum=0.0;
				for(int j=0; j<i; ++j) {
					sum-=ma0[i][j]*x_k1[j];
				}
				for(int j=i; j<row; ++j) {
					sum-=ma0[i][j]*x_k0[j];
				}
				sum+=coefficientB[i];
				sum*=omega;
				sum/=ma0[i][i];
				sum+=x_k0[i];
				x_k1[i]=sum;
			}
			VectorMinus(x_k1,x_k0,x_diff,row);
			VectorCopy(x_k1,x_k0,row);
#ifdef DEBUG
			printf("x_k1=\n");
			output1D(x_k1,row);
			printf("x_diff=\n");
			output1D(x_diff,row);
			printf(
			    "x_diff的2范数 = \n"
			    "%14.10lf\n"
			    ,Norm2(x_diff,row));
#endif

			//当SOR的结果超过既定的最大值INF时, 判定为发散:
			for(int i=0; i<row; ++i) {
			if(fabs(x_k1[i])>=INF) {
					isDiverge=true;
					break;
				}
			}
			if(isDiverge) {
				break;
			}
		} while(Norm2(x_diff,row)>=eps);

		if(isDiverge) {
			isDiverge=false;
			printf("SOR发散....\n");
		} else {
			printf(
			    "最终结果: \n"
			    "经过%d次迭代\n"
			    "最终结果: x_k1=\n"
			    ,k);
			output1D(x_k1,row);
			printf(
			    "\n"
			    "-------------------------------------------\n");
		}

	}
#endif
	return 0;
}

//向量减法:
void VectorMinus(double a[N],double b[N],double ans[N],int n) {
	const double MINIMUM=pow(10,-11);
	for(int i=0; i<n; ++i) {
		ans[i]=a[i]-b[i];
		if(ans[i]<MINIMUM) {
			ans[i]=0;
		}
	}
	return ;
}

//向量复制:
void VectorCopy(double src[N],double dst[N],int n) {
	for(int i=0; i<n; ++i) {
		dst[i]=src[i];
	}
	return ;
}

//求向量的2范数:
double Norm2(double a[N],int n) {
	double sum=0.0;
	for(int i=0; i<n; ++i) {
		sum+=fabs(a[i]*a[i]);
	}
	return sqrt(sum);
}

void input1D(double vec[N], int n) {
	for(int i=0; i<n; ++i) {
		scanf("%lf",&vec[i]);
	}
	return ;
}

void input2D(double matrix[N][N],int n) {
	for(int i=0; i<n; ++i) {
		input1D(matrix[i],n);
	}
	return ;
}

void output1D(double vec[N],int n) {
	for(int i=0; i<n; ++i) {
		printf("%+18.10lf ",vec[i]);
	}
	putchar('\n');
	return ;
}

void output2D(double matrix[N][N], int n) {
	for(int i=0; i<n; ++i) {
		output1D(matrix[i],n);
	}
	putchar('\n');
	return ;
}

void iniA(double a[N][N], int n) {
	for(int i=0; i<n; ++i) {
		for(int j=0; j<n; ++j) {
			a[i][j]= 1.0/(i+j+1);
		}
	}
	return ;
}

void iniB(double b[N],int n) {
	double sum=0;
	for(int i=0; i<n; ++i) {
		sum=0;
		for(int j=0; j<n; ++j) {
			sum+=1.0/(i+j+1);
		}
		b[i]=sum;
	}
	return ;
}


CG:

#include <iostream>
#include <cmath>
#include <cstring>

//#define DEBUG		//DEBUG用, 增加更多的输出
//#define PRO_1		//第一题时需要定义


using namespace std;

const int N=30;
const int INF=10000;

void iniA(double a[N][N], int n) ;
void iniB(double b[N],int n);
void input1D(double vec[N], int n) ;
void input2D(double matrix[N][N],int n);
void output1D(double vec[N],int n);
void output2D(double matrix[N][N], int n);
double VectorMtimes(double a[N], double b[N],int n);
void VectorPlus(double a[N],double b[N], double ans[N], int n);
void VectorMinus(double a[N],double b[N],double ans[N],int n) ;
void MatrixMtimes(double a[N][N], double b[N],double ans[N],int n) ;
void VectorCopy(double src[N],double dst[N],int n) ;
double Norm2(double a[N],int n) ;
double NormInf(double a[N],int n);



int main(void) {

	double a[N][N]= {0};
	double b[N]= {0};
	double x_k1[N]= {0};
	double x_k0[N]= {0};
	double eps=0.0;
	double r_k0[N]= {0};
	double p_k0[N]= {0};
	double beta=0.0;
	double alpha=0.0;
	double tempAns[N]= {0};
	double tempAns2[N]= {0};


//--------------------------------------
//第一题:
#ifdef PRO_1
	//默认矩阵为方阵
	int row=0;
	printf(
	    "输入矩阵的行列:\n"
	    "row = column =  ");
	scanf("%d",&row);

	printf("输入矩阵A:\n");
	input2D(a,row);

	printf("输入系数矩阵B:\n");
	input1D(b,row);

#ifdef DEBUG
	printf("输入的矩阵A为:\n");
	output2D(a,row);
	printf("输入的系数b为:\n");
	output1D(b,row);
#endif

	printf("输入初始X0 = ");
	for(int i=0; i<row; ++i) {
		scanf("%lf",&x_k0[i]);
	}

	printf("输入终止条件: eps = ");
	scanf("%lf",&eps);

//计算初次迭代的各个初值:

	//r=b-Ax
	memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
	MatrixMtimes(a,x_k0,tempAns,row);
	VectorMinus(b,tempAns,r_k0,row);

	//p=r
	VectorCopy(r_k0,p_k0,row);

	//α= r^T*r/(p^T*A*p)
	memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
	MatrixMtimes(a,p_k0,tempAns,row);
	alpha=VectorMtimes(r_k0,r_k0,row)/VectorMtimes(p_k0,tempAns,row);

	//x'=x+αp
	memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
	for(int i=0; i<row; ++i) {
		tempAns[i]=p_k0[i]*alpha;
	}
	VectorPlus(x_k0,tempAns,x_k1,row);

#ifdef DEBUG
	printf(
	    "初始值:\n"
	    "r=\n"
	);
	output1D(r_k0,row);
	printf("p = \n");
	output1D(p_k0,row);
	printf("x_k0 = \n");
	output1D(x_k0,row);
	printf("x_k1 = \n");
	output1D(x_k1,row);
	printf("alpha = %lf\n",alpha);
#endif

	int k=0;
	double diff=0.0;
	double isDiverge=0;

	do {
		k++;

		//r=b-Ax
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		MatrixMtimes(a,x_k1,tempAns,row);
		VectorMinus(b,tempAns,r_k0,row);
#ifdef DEBUG
		printf("tempAns = \n");
		output1D(tempAns,row);
#endif

		//β=r^TAp/p^TAp
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		MatrixMtimes(a,p_k0,tempAns,row);
		beta=-VectorMtimes(r_k0,tempAns,row)/VectorMtimes(p_k0,tempAns,row);

		//p'=r+βp
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		for(int i=0; i<row; ++i) {
			tempAns[i]=p_k0[i]*beta;
		}
		VectorPlus(r_k0,tempAns,p_k0,row);

		//α=r^Tp/p^TAp
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		MatrixMtimes(a,p_k0,tempAns,row);
		alpha=VectorMtimes(r_k0,p_k0,row)/VectorMtimes(p_k0,tempAns,row);

		//x'=x+αp
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		memset(tempAns2,0,sizeof(double)*N);	//中间结果tempAns2清零
		for(int i=0; i<row; ++i) {
			tempAns[i]=p_k0[i]*alpha;
		}
		VectorPlus(x_k1,tempAns,tempAns2,row);
		VectorCopy(tempAns2,x_k1,row);

		//使用diff残差判定:
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		memset(tempAns2,0,sizeof(double)*N);	//中间结果tempAns2清零
		MatrixMtimes(a,x_k1,tempAns,row);
		VectorMinus(b,tempAns,tempAns2,row);
		diff=NormInf(tempAns2,row)/NormInf(b,row);

#ifdef DEBUG
		printf("第%d次循环\n",k);
		printf("r = \n");
		output1D(r_k0,row);
		printf("p = \n");
		output1D(p_k0,row);
		printf("x_k0 = \n");
		output1D(x_k0,row);
		printf("x_k1 = \n");
		output1D(x_k1,row);
		printf("alpha = %lf\n",alpha);
		printf("beta = %lf\n",beta);
		printf("diff = %lf\n",diff);
#endif
		//当CG的结果超过既定的最大值INF时, 判定为发散:
		for(int i=0; i<row; ++i) {
			if(fabs(x_k1[i])>=INF) {
				isDiverge=true;
				break;
			}
		}
		if(isDiverge) {
			break;
		}

	} while(fabs(diff)>=eps);

	if(isDiverge) {
		isDiverge=false;
		printf("CG发散\n");
	} else {
		printf(
		    "最终结果\n"
		    "经过%d次迭代\n"
		    "x_k1 = \n"
		    ,k);
		output1D(x_k1,row);
	}



//---------------------------------------
//第二题:
#else
	int ROW=0, row=0;
	printf("输入方阵的最大行数: ROW = ");
	scanf("%d",&ROW);
	while(row<ROW) {
		++row;
		printf("row = %d\n",row);
		iniA(a,row);
		iniB(b,row);
		eps=0.000001;
#ifdef DEBUG
		printf("矩阵A:\n");
		output2D(a,row);
		printf("系数矩阵B:\n");
		output1D(b,row);
#endif
//计算初次迭代的各个初值:

		//r=b-Ax
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		MatrixMtimes(a,x_k0,tempAns,row);
		VectorMinus(b,tempAns,r_k0,row);

		//p=r
		VectorCopy(r_k0,p_k0,row);

		//α= r^T*r/(p^T*A*p)
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		MatrixMtimes(a,p_k0,tempAns,row);
		alpha=VectorMtimes(r_k0,r_k0,row)/VectorMtimes(p_k0,tempAns,row);

		//x'=x+αp
		memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
		for(int i=0; i<row; ++i) {
			tempAns[i]=p_k0[i]*alpha;
		}
		VectorPlus(x_k0,tempAns,x_k1,row);

#ifdef DEBUG
		printf(
		    "初始值:\n"
		    "r=\n"
		);
		output1D(r_k0,row);
		printf("p = \n");
		output1D(p_k0,row);
		printf("x_k0 = \n");
		output1D(x_k0,row);
		printf("x_k1 = \n");
		output1D(x_k1,row);
		printf("alpha = %lf\n",alpha);
#endif

		int k=0;
		double diff=0.0;
		bool isDiverge=false;

		do {
			k++;

			//r=b-Ax
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			MatrixMtimes(a,x_k1,tempAns,row);
			VectorMinus(b,tempAns,r_k0,row);
#ifdef DEBUG
			printf("tempAns = \n");
			output1D(tempAns,row);
#endif

			//β=r^TAp/p^TAp
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			MatrixMtimes(a,p_k0,tempAns,row);
			beta=-VectorMtimes(r_k0,tempAns,row)/VectorMtimes(p_k0,tempAns,row);

			//p'=r+βp
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			for(int i=0; i<row; ++i) {
				tempAns[i]=p_k0[i]*beta;
			}
			VectorPlus(r_k0,tempAns,p_k0,row);

			//α=r^Tp/p^TAp
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			MatrixMtimes(a,p_k0,tempAns,row);
			alpha=VectorMtimes(r_k0,p_k0,row)/VectorMtimes(p_k0,tempAns,row);

			//x'=x+αp
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			memset(tempAns2,0,sizeof(double)*N);	//中间结果tempAns2清零
			for(int i=0; i<row; ++i) {
				tempAns[i]=p_k0[i]*alpha;
			}
			VectorPlus(x_k1,tempAns,tempAns2,row);
			VectorCopy(tempAns2,x_k1,row);

			//diff=
			memset(tempAns,0,sizeof(double)*N);		//中间结果tempAns清零
			memset(tempAns2,0,sizeof(double)*N);	//中间结果tempAns2清零
			MatrixMtimes(a,x_k1,tempAns,row);
			VectorMinus(b,tempAns,tempAns2,row);
			diff=NormInf(tempAns2,row)/NormInf(b,row);
#ifdef DEBUG
			printf("第%d次循环\n",k);
			printf("r = \n");
			output1D(r_k0,row);
			printf("p = \n");
			output1D(p_k0,row);
			printf("x_k0 = \n");
			output1D(x_k0,row);
			printf("x_k1 = \n");
			output1D(x_k1,row);
			printf("alpha = %lf\n",alpha);
			printf("beta = %lf\n",beta);
			printf("diff = %lf\n",diff);
#endif
			//当CG的结果超过既定的最大值INF时, 判定为发散:
			for(int i=0; i<row; ++i) {
				if(fabs(x_k1[i])>=INF) {
					isDiverge=true;
					break;
				}
			}
			if(isDiverge) {
				break;
			}
		} while(fabs(diff)>=eps);

		if(isDiverge) {
			isDiverge=false;
			printf("CG发散\n");
		} else {
			printf(
			    "最终结果\n"
			    "经过%d次迭代\n"
			    "x_k1 = \n"
			    ,k);
			output1D(x_k1,row);
		}

	}


#endif

	return 0;
}

//向量乘法:
//a[1*n] * b[n*1]
double VectorMtimes(double a[N], double b[N],int n) {
	double ans=0.0;
	for(int i=0; i<n; ++i) {
		ans+=a[i]*b[i];
	}
	return ans;
}

//向量加法:
//a[n] + b[n]
void VectorPlus(double a[N],double b[N], double ans[N], int n) {
	for(int i=0; i<n; ++i) {
		ans[i]=a[i]+b[i];
	}
	return ;
}

//向量减法:
//a[n] - b[n]
void VectorMinus(double a[N],double b[N],double ans[N],int n) {
	for(int i=0; i<n; ++i) {
		ans[i]=a[i]-b[i];
	}
	return ;
}

//方阵乘法:
//a[n*n] * b[n*1]
void MatrixMtimes(double a[N][N], double b[N],double ans[N],int n) {
	memset(ans,0,sizeof(double)*N);
	for(int i=0; i<n; ++i) {
		for(int j=0; j<n; ++j) {
			ans[i]+=a[i][j]*b[j];
		}
	}
	return ;
}

//向量复制:
void VectorCopy(double src[N],double dst[N],int n) {
	for(int i=0; i<n; ++i) {
		dst[i]=src[i];
	}
	return ;
}


//求向量的2范数:
double Norm2(double a[N],int n) {
	double sum=0.0;
	for(int i=0; i<n; ++i) {
		sum+=fabs(a[i]*a[i]);
	}
	return sqrt(sum);
}

//求向量的1范数:
double Norm1(double a[N],int n) {
	double sum=0.0;
	for(int i=0; i<n; ++i) {
		sum+=fabs(a[i]);
	}
	return sum;
}

//求向量的Inf范数
double NormInf(double a[N],int n) {
	double maxValue=a[0];
	for(int i=1; i<n; ++i) {
		maxValue=maxValue<a[i]?a[i]:maxValue;
	}
	return maxValue;
}

//求N阶方阵a 的Inf范数
double MatrixNormInf(double a[N][N], int n) {
	double maxValue=Norm1(a[0],n);
	for(int i=1; i<n; ++i) {
		maxValue=maxValue<Norm1(a[i],n)?Norm1(a[i],n):maxValue;
	}
	return maxValue;
}


void iniA(double a[N][N], int n) {
	for(int i=0; i<n; ++i) {
		for(int j=0; j<n; ++j) {
			a[i][j]= 1.0/(i+j+1);
		}
	}
	return ;
}

void iniB(double b[N],int n) {
	double sum=0;
	for(int i=0; i<n; ++i) {
		sum=0;
		for(int j=0; j<n; ++j) {
			sum+=1.0/(i+j+1);
		}
		b[i]=sum;
	}
	return ;
}

void input1D(double vec[N], int n) {
	for(int i=0; i<n; ++i) {
		scanf("%lf",&vec[i]);
	}
	return ;
}

void input2D(double matrix[N][N],int n) {
	for(int i=0; i<n; ++i) {
		input1D(matrix[i],n);
	}
	return ;
}

void output1D(double vec[N],int n) {
	for(int i=0; i<n; ++i) {
		printf("%+18.10lf ",vec[i]);
	}
	putchar('\n');
	return ;
}

void output2D(double matrix[N][N], int n) {
	for(int i=0; i<n; ++i) {
		output1D(matrix[i],n);
	}
	putchar('\n');
	return ;
}


实验四:

源码:

#include <iostream>
#include <cmath>

using namespace std;

#define DEBUG

void Thomas(double a[], double b[],double c[],double f[],double ans[],int n);
double function(double x);
void output(double arr[], int n);


int main(void) {
	int n=0;
	printf("输出三次样条差值的分段数N=");
	scanf("%d",&n);

	//输入各段Xi
	double x[n+1]= {0};
	printf("输入各个段点值Xi:");
	for(int i=0; i<n+1; ++i) {
		scanf("%lf",&x[i]);
	}

	//求解Hi
	double h[n+1]= {0};
	for(int i=1; i<n+1; ++i) {
		h[i]=x[i]-x[i-1];
	}

	//输入两个端点值
	double y_0=0.0,y_n=0.0;
	printf("输出两端点导数值 Y0' 与 Yn' :");
	scanf("%lf",&y_0);
	scanf("%lf",&y_n);

	//求解Yi
	double y[n+1];
	for(int i=0; i<n+1; ++i) {
		y[i]=function(x[i]);
	}

	//几个使用到的变量:
	double d[n+1]= {0};
	double c[n+1]= {0};
	double lambda[n+1]= {0};
	double miu[n+1]= {0};
	double M[n+1]= {0};
	//进入处理循环
	for(int i=1; i<n+1; ++i) {
		d[i]=6*((y[i+1]-y[i])/h[i+1]-(y[i]-y[i-1])/h[i])/(h[i]+h[i+1]);
		c[i]=2;
		lambda[i]=h[i+1]/(h[i]+h[i+1]);
		miu[i]=1-lambda[i];
	}
	//DEBUG: d,c,lambda,miu=?

	//转化为Thomas追赶法的参数:
	double Thomas_a[n-1]= {0};
	double Thomas_b[n-1]= {0};
	double Thomas_c[n-1]= {0};
	double Thomas_f[n-1]= {0};
	double ans[n-1]= {0};
	Thomas_b[0]=c[1];
	Thomas_f[0]=d[1];
	for(int i=1; i<=n-2; ++i) {
		Thomas_a[i]=miu[i+1];
		Thomas_b[i]=c[i+1];
		Thomas_c[i-1]=lambda[i];
		Thomas_f[i]=d[i+1];
	}
	//DEBUG: Thomas_a,Thomas_b,Thomas_c,Thomas_f=?
	Thomas(Thomas_a,Thomas_b,Thomas_c,Thomas_f,ans,n-1);
	//DEBUG: ans=?

	//将追赶法的结果提取到M中:
	for(int i=1; i<n; i++) {
		M[i]=ans[i-1];
	}
	//DEBUG: M=?

	//求解端点值:
	M[0] = (6 * ((y[1] - y[0]) / h[1] - y_0) / h[1] - M[1]) / 2;
	M[n] = (6 * (y_n - (y[n] - y[n - 1]) / h[n]) / h[n] - M[n - 1]) / 2;
	//DEBUG: M=?


	//准备inputX
	int inputTime=20;
	double inputX[inputTime]= {0};		//inputX[0]为空
	for(int i=1; i<inputTime+1; ++i) {
		inputX[i]=-1.05+0.1*i;
	}
	//DEBUG: inputX=?

	

	//求解最终的S_tar(Xi)
	int tar=1;
	double S_tar[inputTime+1]= {0};
	for(int i=1; i<inputTime+1; ++i,++tar) {
		S_tar[i]=M[tar-1]*pow(x[tar]-inputX[i],3)/(6*h[tar])+
		         M[tar]*pow(inputX[i]-x[tar-1],3)/(6*h[tar])+
		         (y[tar-1]-M[tar-1]/6*h[tar]*h[tar])*(x[tar]-inputX[i])/h[tar]+
		         (y[tar]-M[tar]/6*h[tar]*h[tar])*(inputX[i]-x[tar-1])/h[tar];
	}


	//求解Lagrange差值:
	double sum=0, mul=1;
	double L_tar[inputTime+1]= {0};
	for(int i=1; i<inputTime+1; ++i) {
		sum=0;
		for(int j=0; j<n+1; ++j) {
			mul=1;
			for(int k=0; k<n+1; ++k) {
				if(k!=j) {
					mul*=(inputX[i]-x[k])/(x[j]-x[k]);
				}
			}
			sum+=mul*y[j];
		}
		L_tar[i]=sum;
	}
	//DEBUG: L_tar=?


	//输出最终结果:
	printf("\n\n最终结果:\n");
	for(int i=1; i<inputTime+1; ++i) {
		printf("x_%2d = %+.2lf    f(%+.2lf) = %+17.14lf   S_%2d = %+17.14lf   L_%2d = %+17.14lf \n",
		       i,inputX[i],inputX[i],function(inputX[i]),i,S_tar[i],i,L_tar[i]);
	}

	return 0;
}

void output(double arr[], int n) {
	for(int i=0; i<n; ++i) {
		printf("%.12lf ",arr[i]);
	}
	return ;
}

double function(double x) {
	return 1/(1+25*x*x);
}

//Thomas追赶法解n阶三对角矩阵, 注意是n阶
void Thomas(double a[], double b[],double c[],double f[],double ans[],int n) {
	double beta[n-1]= {0};
	double y[n]= {0};

	beta[0]=c[0]/b[0];
	for(int i=0; i<n; ++i) {
		beta[i]=c[i]/(b[i]-a[i]*beta[i-1]);
	}

	y[0]=f[0]/b[0];
	for(int i=1; i<n; ++i) {
		y[i]=(f[i]-a[i]*y[i-1])/(b[i]-a[i]*beta[i-1]);
	}

	ans[n-1]=y[n-1];

	for(int i=n-2; i>=0; --i) {
		ans[i]=y[i]-beta[i]*ans[i+1];
	}

	return;
}


输入输出:

输出三次样条差值的分段数N=20
输入各个段点值Xi:
-1 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
输出两端点导数值 Y0’ 与 Yn’ :
0.07396449704142012

0.07396449704142012

最终结果:
x_ 1 = -0.95 f(1717986919) = +0.04244031830239 S_ 1 = +0.04242204208118 L_ 1 = -39.95244903304251
x_ 2 = -0.85 f(858993460) = +0.05245901639344 S_ 2 = +0.05243128736673 L_ 2 = +3.45495779986415
x_ 3 = -0.75 f( 0) = +0.06639004149378 S_ 3 = +0.06639405338251 L_ 3 = -0.44705196070884
x_ 4 = -0.65 f(-858993459) = +0.08648648648649 S_ 4 = +0.08647363117869 L_ 4 = +0.20242261570456
x_ 5 = -0.55 f(-1717986918) = +0.11678832116788 S_ 5 = +0.11678687446503 L_ 5 = +0.08065999342165
x_ 6 = -0.45 f(-858993460) = +0.16494845360825 S_ 6 = +0.16486455736328 L_ 6 = +0.17976262990060
x_ 7 = -0.35 f(1717986918) = +0.24615384615385 S_ 7 = +0.24626815868132 L_ 7 = +0.23844593373813
x_ 8 = -0.25 f( 0) = +0.39024390243902 S_ 8 = +0.38941957183718 L_ 8 = +0.39509305368778
x_ 9 = -0.15 f(858993460) = +0.64000000000000 S_ 9 = +0.64316893858536 L_ 9 = +0.63675533591643
x_10 = -0.05 f(-1717986912) = +0.94117647058824 S_10 = +0.93886621228293 L_10 = +0.94249037974398
x_11 = +0.05 f(-1717986912) = +0.94117647058824 S_11 = +0.93886621228293 L_11 = +0.94249037974398
x_12 = +0.15 f(858993464) = +0.64000000000000 S_12 = +0.64316893858536 L_12 = +0.63675533591643
x_13 = +0.25 f( 0) = +0.39024390243902 S_13 = +0.38941957183718 L_13 = +0.39509305368778
x_14 = +0.35 f(1717986920) = +0.24615384615385 S_14 = +0.24626815868132 L_14 = +0.23844593373813
x_15 = +0.45 f(-858993460) = +0.16494845360825 S_15 = +0.16486455736328 L_15 = +0.17976262990060
x_16 = +0.55 f(-1717986918) = +0.11678832116788 S_16 = +0.11678687446503 L_16 = +0.08065999342165
x_17 = +0.65 f(-858993458) = +0.08648648648649 S_17 = +0.08647363117869 L_17 = +0.20242261570456
x_18 = +0.75 f( 0) = +0.06639004149378 S_18 = +0.06639405338251 L_18 = -0.44705196070884
x_19 = +0.85 f(858993460) = +0.05245901639344 S_19 = +0.05243128736673 L_19 = +3.45495779986420
x_20 = +0.95 f(1717986918) = +0.04244031830239 S_20 = +0.03964837344213 L_20 = -39.95244903304321

实验五:

#include <iostream>
#include <cmath>
#include <cfloat>

//#define DEBUG

using namespace std;

//order表示拟合函数幂次
const int order=3;

double function(double x);
void Gauss_Seidel_Iteration(double ma0[order+1][order+1], double b[order+1] ,
                            double ans[order+1]) ;
void MatrixMinus(double ma0[], double ma1[], double ans[],int n);
void MatrixCopy(double src[],double dst[],int n);
double NormInf(double vec[],int n);
void Thomas(double a[], double b[],double c[],double f[],double ans[],int n) ;
void Lagrange(double L_tar[],int inputTime,double inputX[], double x[], double y[]);
void spline(int n,double x[], double y[], double inputX[],double S_tar[]) ;


int main(void) {

	//对Phi进行赋值, 这里使用函数指针和Lambda表达式
	const int MAX_ORDER=4;
	double(*Phi[MAX_ORDER+1])(double x) = {0};
	Phi[0]=[](double x)->double {return pow(x,0);};
	Phi[1]=[](double x)->double {return pow(x,1);};
	Phi[2]=[](double x)->double {return pow(x,2);};
	Phi[3]=[](double x)->double {return pow(x,3);};
	Phi[4]=[](double x)->double {return pow(x,4);};

	int max_iteration=0;
	printf("输入n的最大值max_iteration = ");
	scanf("%d",&max_iteration);
	int n=1;
	while(n<max_iteration) {
		++n;
#ifdef DEBUG		
		n=20;
#endif
		printf("第%d次迭代, n=%d",n,n);

		//测试用:
//		n=4;

		//求Xi
		//测试用:
//		double x[n+1]= {0.0,0.25,0.5,0.75,1.0};
		double x[n+1]= {0};
		for(int i=0; i<n+1; ++i) {
			x[i]=-1+2.0*i/n;
		}
		//DEBUG: X=?


		//求解Yi
		//测试用:
//		double y[n+1]= {1.0,1.2840,1.6487,2.1170,2.7183};
		double y[n+1]= {0};
		for(int i=0; i<n+1; ++i) {
			y[i]=function(x[i]);
		}
		//DEBUG: Y=?

		//求解Gram矩阵
		double gram[order+1][order+1]= {0};
		double tempSum=0.0;
		for(int i=0; i<order+1; ++i) {
			for(int j=0; j<order+1; ++j) {
				tempSum=0.0;
				for(int k=0; k<n+1; ++k) {
					tempSum+=Phi[i](x[k])*Phi[j](x[k]);
				}
				gram[i][j]=tempSum;
			}
		}
		//DEBUG: gram=?

		//求解系数矩阵d:
		double d[order+1]= {0};
		for(int i=0; i<order+1; ++i) {
			tempSum=0.0;
			for(int j=0; j<n+1; ++j) {
				tempSum+=Phi[i](x[j])*y[j];
			}
			d[i]=tempSum;
		}
		//DEBUG: d=?

		//求解线性方程组:
		double a[order+1]= {0};
		Gauss_Seidel_Iteration(gram,d,a);
		//DEBUG: a=?

		//准备inputX
		double inputX[n+1]= {0};	//inputX[0]为空
		for(int i=1; i<n+1; ++i) {
			inputX[i]=(x[i]+x[i-1])/2;
		}
		//DEBUG: inputX=?
		
		//计算最小二乘拟合的结果:
		double s_star[n+1]= {0};
		for(int i=0; i<n+1; ++i) {
			for(int j=0; j<order+1; ++j) {
				s_star[i]+=Phi[j](inputX[i])*a[j];
			}
		}


//---------------------------------------------
		//计算Lagrange差值的结果:
		double L_tar[n+1]= {0};
		if(n>2) {
			Lagrange(L_tar,n,inputX,x,y);
		}
		//DEBUG: L_tar=?
//---------------------------------------------
		//计算三次样条差值的结果:
		double S_tar[n+1]= {0};
		if(n>2) {
			spline(n,x,y,inputX,S_tar);
		}
//---------------------------------------------

		//输出结果:
		printf("\n\n最终结果:\n");
		for(int i=1; i<n+1; ++i) {
			printf("Xi = %+.3lf   S_*(Xi) = %+18.14lf   S_%2d  = %+18.14lf\n"
			       "              L_%2d    = %+18.14lf   f(Xi) = %+18.14lf\n\n"
			       ,inputX[i],s_star[i],i,S_tar[i],i,L_tar[i],function(inputX[i]));
		}
	}
	return 0;
}

double function(double x) {
	return 1/(1+25*x*x);
}

//使用 Gauss_Seidel 迭代法求解线性方程组
void Gauss_Seidel_Iteration(double ma0[order+1][order+1], double b[order+1] ,
                            double ans[order+1]) {
	double x_k1[order+1]= {0};
	double x_k0[order+1]= {0};
	double x_diff[order+1]= {0};
	double eps=0.000001;
	int k=0;
	double sum=0.0;

	do {
		k++;
		for(int i=0; i<order+1; ++i) {
			sum=0.0;
			for(int j=0; j<i; ++j) {
				sum+=ma0[i][j]*x_k1[j];
			}
			for(int j=i+1; j<order+1; ++j) {
				sum+=ma0[i][j]*x_k0[j];
			}
			sum-=b[i];
			sum/=(-ma0[i][i]);
			x_k1[i]=sum;
		}
		MatrixMinus(x_k1,x_k0,x_diff,order+1);
		MatrixCopy(x_k1,x_k0,order+1);
	} while(NormInf(x_diff,order+1)>=eps);
	MatrixCopy(x_k1,ans,order+1);
}

void MatrixMinus(double ma0[], double ma1[], double ans[],int n) {
	for(int i=0; i<n; ++i) {
		ans[i]=ma0[i]-ma1[i];
	}
	return ;
}
//向量复制 
void MatrixCopy(double src[],double dst[],int n) {
	for(int i=0; i<n; ++i) {
		dst[i]=src[i];
	}
	return ;
}
//求解向量Inf范数 
double NormInf(double vec[],int n) {
	double max=DBL_MIN;
	for(int i=0; i<n; ++i) {
		max>vec[i]?max=max:max=vec[i];
	}
	return max;
}

//三次样条差值:
//n: 分段个数
//x: 各个段点值
//y: f(x)
//inputX: 输入的测试x值
//S_tar: 最终结果
void spline(int n,double x[], double y[], double inputX[],double S_tar[]) {
	//求解Hi
	double h[n+1]= {0};
	for(int i=1; i<n+1; ++i) {
		h[i]=x[i]-x[i-1];
	}

	//输入两个端点值
	double y_0=0.07396449704142012,y_n=0.07396449704142012;
//	printf("输出两端点值 Y0' 与 Yn' :");
//	scanf("%lf",&y_0);
//	scanf("%lf",&y_n);

	//几个使用到的变量:
	double d[n+1]= {0};
	double c[n+1]= {0};
	double lambda[n+1]= {0};
	double miu[n+1]= {0};
	double M[n+1]= {0};
	//进入处理循环
	for(int i=1; i<n+1; ++i) {
		d[i]=6*((y[i+1]-y[i])/h[i+1]-(y[i]-y[i-1])/h[i])/(h[i]+h[i+1]);
		c[i]=2;
		lambda[i]=h[i+1]/(h[i]+h[i+1]);
		miu[i]=1-lambda[i];
	}
	//DEBUG: d,c,lambda,miu=?

	//转化为Thomas追赶法的参数:
	double Thomas_a[n-1]= {0};
	double Thomas_b[n-1]= {0};
	double Thomas_c[n-1]= {0};
	double Thomas_f[n-1]= {0};
	double ans[n-1]= {0};
	Thomas_b[0]=c[1];
	Thomas_f[0]=d[1];
	for(int i=1; i<=n-2; ++i) {
		Thomas_a[i]=miu[i+1];
		Thomas_b[i]=c[i+1];
		Thomas_c[i-1]=lambda[i];
		Thomas_f[i]=d[i+1];
	}
	//DEBUG: Thomas_a,Thomas_b,Thomas_c,Thomas_f=?
	Thomas(Thomas_a,Thomas_b,Thomas_c,Thomas_f,ans,n-1);
	//DEBUG: ans=?

	//将追赶法的结果提取到M中:
	for(int i=1; i<n; i++) {
		M[i]=ans[i-1];
	}
	//DEBUG: M=?

	//求解端点值:
	M[0]=(6*((y[1]-y[0])/h[1]-y_0)/h[1]-M[1])/2;
	M[n]=(6*(y_n-(y[n]-y[n-1])/h[n])/h[n]-M[n-1])/2;
	//DEBUG: M=?

	//求解最终的S20(Xi)
	int tar=1;
//	double S_tar[inputTime+1]= {0};

	for(int i=1; i<n+1; ++i,++tar) {
		S_tar[i]=M[tar-1]*pow(x[tar]-inputX[i],3)/(6*h[tar])+
		         M[tar]*pow(inputX[i]-x[tar-1],3)/(6*h[tar])+
		         (y[tar-1]-M[tar-1]/6*h[tar]*h[tar])*(x[tar]-inputX[i])/h[tar]+
		         (y[tar]-M[tar]/6*h[tar]*h[tar])*(inputX[i]-x[tar-1])/h[tar];
	}
	
	return ;
}

//---------------------------------------------
//tar: 插值多项式的次数
//L_tar: 最终结果
//inputTime: 输入的测试X的个数
//inputX[]: 输入的x的值,[inputTime+1]
//x[]: 段点值
//y[]: 段点函数值 
void Lagrange(double L_tar[],int inputTime,double inputX[], double x[], double y[]) {
	double sum=0, mul=1;
	for(int i=1; i<inputTime+1; ++i) {
		sum=0;
		for(int j=0; j<inputTime+1; ++j) {
			mul=1;
			for(int k=0; k<inputTime+1; ++k) {
				if(k!=j) {
					mul*=(inputX[i]-x[k])/(x[j]-x[k]);
				}
			}
			sum+=mul*y[j];
		}
		L_tar[i]=sum;
	}

	return ;
}

//Thomas追赶法解n阶三对角矩阵, 注意是n阶
void Thomas(double a[], double b[],double c[],double f[],double ans[],int n) {
	double beta[n-1]= {0};
	double y[n]= {0};

	beta[0]=c[0]/b[0];
	for(int i=0; i<n; ++i) {
		beta[i]=c[i]/(b[i]-a[i]*beta[i-1]);
	}

	y[0]=f[0]/b[0];
	for(int i=1; i<n; ++i) {
		y[i]=(f[i]-a[i]*y[i-1])/(b[i]-a[i]*beta[i-1]);
	}

	ans[n-1]=y[n-1];

	for(int i=n-2; i>=0; --i) {
		ans[i]=y[i]-beta[i]*ans[i+1];
	}

	return;
}


实验六:

在这里插入图片描述

源码:

#include <iostream>
#include <cmath>

//#define DEBUG

using namespace std;

//数组默认的最大容量 
const int MAX=105;

double function(double x) ;

int main(int argc, char* argv[]) {

	double a=0.0, b=0.0;
	printf("输入区间[a,b] = ");
	scanf("%lf",&a);
	scanf("%lf",&b);

	double eps=0.0;
	printf("输入精度 eps = ");
	scanf("%lf",&eps);

	double T[MAX]= {0};
	double S[MAX]= {0};
	double C[MAX]= {0};
	double R[MAX]= {0};
	double h=0.0;		//中间变量 
	double sum=0.0;		//中间变量 

	T[0]=(b-a)/2*(function(a)+function(b));

	//求到T16
	for(int temp=1; temp<5; ++temp) {
		sum=0.0;
		h=(b-a)/pow(2,temp);
		for(int i=1; i<=pow(2,temp); ++i) {
			sum+=2*function(a+h*i);
		}
		sum+=(function(a)-function(b));
		T[temp]=h/2*sum;
	}
	//求到S8
	for(int temp=0; temp<4; ++temp) {
		S[temp]=T[temp+1]+(T[temp+1]-T[temp])/3;
	}
	//求到C4
	for(int temp=0; temp<3; ++temp) {
		C[temp]=S[temp+1]+(S[temp+1]-S[temp])/15;
	}
	//求到R2:
	for(int temp=0; temp<2; ++temp) {
		R[temp]=C[temp+1]+(C[temp+1]-C[temp])/63;
	}

	//用于指向各个数组的下标
	//T[4]=T16, S[3]=S8, C[2]=C4, R[1]=R2
	int pT=4, pS=3, pC=2, pR=1;

	//最少执行2次循环 : 
	int count=0;	//用于记录循环次数 
	while(count<2||fabs(R[pR]-R[pR-1])>=eps) {
#ifdef DEBUG
		printf("%d\n",count);
#endif		
		++count;
		sum=0.0;
		h=(b-a)/pow(2,pT+1);
		for(int i=1; i<=pow(2,pT+1); ++i) {
			sum+=2*function(a+h*i);
		}
		sum+=(function(a)-function(b));
		T[pT+1]=h/2*sum;
		++pT;
		
		S[pS+1]=T[pT]+(T[pT]-T[pT-1])/3;
		++pS;
		C[pC+1]=S[pS]+(S[pS]-S[pS-1])/15;
		++pC;
		R[pR+1]=C[pC]+(C[pC]-C[pC-1])/63;
		++pR;
	}
	printf("\nT: \n");
	for(int j=0; j<=pT; ++j) {
		printf("%18.14lf", T[j]);
	}
	printf("\nS: \n");
	for(int j=0; j<=pS; ++j) {
		printf("%18.14lf", S[j]);
	}
	printf("\nC: \n");
	for(int j=0; j<=pC; ++j) {
		printf("%18.14lf", C[j]);

	}
	printf("\nR: \n");
	for(int j=0; j<=pR; ++j) {
		printf("%18.14lf", R[j]);

	}

	return 0;
}

double function(double x) {
	//特殊值,无法直接计算 
	if(!x){
		return 1;
	}
//测试用:
//	return exp(x);
	return sin(x)/x;
}

输入输出:

输入区间[a,b] = 0 1

输入精度 eps = 0.000001

T:

0.92073549240395 0.93979328480618 0.94451352166539 0.94569086358270 0.94598502993439 0.94605856096277 0.94607694306006

S:

0.94614588227359 0.94608693395179 0.94608331088847 0.94608308538495 0.94608307130556 0.94608307042583

C:

0.94608300406367 0.94608306935092 0.94608307035138 0.94608307036694 0.94608307036718

R:

0.94608307038722 0.94608307036726 0.94608307036718 0.94608307036718

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值