現將小生研一數值分析作業摘錄如下,上機的代老師要求我們分為四個部分:解題理論依據、計算程序、計算結果截圖和問題討論,因公式輸入不便所以第一部分的公式略去,需要的可去下載附件。因為本人編程水平有限,故使用的是最基本的函數,但保證原創和結果正確,所有程序在VC++6.0上驗證通過,還望各位兄台不吝賜教。
第一題二問):超松弛法求方程組根
1.解題理論依據或方法應用條件:
超松弛算法是在GS方法已求出x(m),x(m-1)的基礎上,經過重新組合得到新序列。如能恰當選擇松弛因子ω,收斂速度會比較快。當ω>1時,稱為超松弛法,可以用來加速收斂。
2.計算程序使用軟件:VC):
#include<stdio.h>
#define w 1.4
main()
{float a[10][10]={ {0,0,0,0,0,0,0,0,0,0},
{0,12.38412,2.115237,-1.061074,1.112336,-0.113584,0.718719,1.742382,3.067813,-2.031743},
{0,2.115237,19.141823,-3.125432,-1.012345,2.189736,1.563849,-0.784165,1.112348,3.123124},
{0,-1.061074,-3.125432,15.567914,3.123848,2.031454,1.836742,-1.056781,0.336993,-1.010103},
{0,1.112336,-1.012345,3.123848,27.108437,4.101011,-3.741856,2.101023,-0.71828,-0.037585},
{0,-0.113584,2.189736,2.031454,4.101011,19.897918,0.431637,-3.111223,2.121314,1.784317},
0,0.718719,1.563849,1.836742,-3.741856,0.431637,9.789365,-0.103458,-1.103456,0.238417},
{0,1.742382,-0.784165,-1.056781,2.101023,-3.111223,-0.103458,14.7138465,3.123789,-2.213474},
{0,3.067813,1.112348,0.336993,-0.71828,2.121314,-1.103456,3.123789,30.719334,4.446782},
{0,-2.031743,3.123124,-1.010103,-0.037585,1.784317,0.238417,-2.213474,4.446782,40.00001}};
float b[10][1]=
{{0},{2.1874369},{33.992318},{-25.173417},{0.84671695},{1.784317},{-86.612343},{1.1101230},{4.719345},{-5.6784392}};
float x[10][10]={{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}; /*由x(0)=0得到其第一列全為零*/
float sum1=0,sum2=0;
int i,m,j;
for(m=1;m<=9;m++)
for(i=1;i<=9;i++)
{sum1=0;
for(j=1;j<=(i-1);j++)sum1+=(-a[i][j]/a[i][i])*x[j][m]; /*計算第一個累加和*/
sum2=0;
for(j=(i+1);j<=9;j++)sum2+=(-a[i][j]/a[i][i])*x[j][m-1]; /*計算第二個累加和*/
x[i][m]=(1-w)*x[i][m-1]+w*(sum1+sum2+b[i][0]/a[i][i]); /*用SOR方法計算*/
}
printf("x1為:%lf\n",x[1][9]);
printf("x2為:%lf\n",x[2][9]);
printf("x3為:%lf\n",x[3][9]);
printf("x4為:%lf\n",x[4][9]);
printf("x5為:%lf\n",x[5][9]);
printf("x6為:%lf\n",x[6][9]);
printf("x7為:%lf\n",x[7][9]);
printf("x8為:%lf\n",x[8][9]);
printf("x9為:%lf\n",x[9][9]);
}
3.計算結果
4.問題討論誤差分析、上機出現情況等)
這道題目是所有題目中編寫最順利的,一次即順利得出結果,當然這道題目還是有應該注意到地方,一是注意兩個求和的清零,二是注意下標,不要弄混行標和列標。
第一題三問):列主元素法求方程組根
1.解題理論依據或方法應用條件:
所謂列主元消去法是,對矩陣作恰當的調整,選取絕對值最大的元素作為主元素。然後把矩陣化為上三角陣,再進行回代,求出方程的解。
2.計算程序使用軟件:VC):
#include<stdio.h>
#include<math.h>
main()
{double a[10][11]={ {0,0,0,0,0,0,0,0,0,0,0},
{0,12.38412,2.115237,-1.061074,1.112336,-0.113584,0.718719,1.742382,3.067813,-2.031743,2.1874369},
{0,2.115237,19.141823,-3.125432,-1.012345,2.189736,1.563849,-0.784165,1.112348,3.123124,33.992318},
{0,-1.061074,-3.125432,15.567914,3.123848,2.031454,1.836742,-1.056781,0.336993,-1.010103,-25.173417},
{0,1.112336,-1.012345,3.123848,27.108437,4.101011,-3.741856,2.101023,-0.71828,-0.037585,0.84671695},
{0,-0.113584,2.189736,2.031454,4.101011,19.897918,0.431637,-3.111223,2.121314,1.784317,1.784317},
{0,0.718719,1.563849,1.836742,-3.741856,0.431637,9.789365,-0.103458,-1.103456,0.238417,-86.612343},
{0,1.742382,-0.784165,-1.056781,2.101023,-3.111223,-0.103458,14.7138465,3.123789,-2.213474,1.1101230},
{0,3.067813,1.112348,0.336993,-0.71828,2.121314,-1.103456,3.123789,30.719334,4.446782,4.719345},
{0,-2.031743,3.123124,-1.010103,-0.037585,1.784317,0.238417,-2.213474,4.446782,40.00001,-5.6784392}};
double x[10],y[11];
double sum=0,max;
int i,j,j1,m,n,k,g,h;
for(j=1;j<=8;j++)
{max=a[j][j];
for(k=j+1;k<=9;k++)
{if(fabs(a[k][j])>fabs(max))max=a[k][j];}
for(k=j;k<=9;k++)
{if(a[k][j]/max==1)g=k;} /*確定本列絕對值最大元素所在行:g行*/
for(h=j;h<=10;h++)
y[h]=a[j][h];
for(h=j;h<=10;h++)
a[j][h]=a[g][h];
for(h=j;h<=10;h++)
a[g][h]=y[h]; /*將g行與J行所有元素進行交換*/
for(i=j+1;i<=9;i++)
for(j1=j+1;j1<=10;j1++)
a[i][j1]-=(a[i][j]/a[j][j])*a[j][j1];} /*逐行消元,將矩陣轉化為上三角矩陣*/
printf("x9為:%lf\n",x[9]=a[9][10]/a[9][9]);
for(m=8;m>=1;m--)
{sum=0;
for(n=m+1;n<=9;n++)
sum+=x[n]*a[m][n];
printf("x%d為:%lf\n",m,x[m]=(a[m][10]-sum)/a[m][m]);} /*從x9到x1逐個解出結果*/
}
3.計算結果
4.問題討論誤差分析、上機出現情況等)
1)這道題目出現的最大問題在 for(j1=j+1;j1<=10;j1++)a[i][j1]-=(a[i][j]/a[j][j])*a[j][j1]; ,剛開始我錯寫為:for(j1=j;j1<=10;j1++)a[i][j1]-=(a[i][j]/a[j][j])*a[j][j1]; ,也就是j1應該從j+1開始取值,如果從j開始取,會導致a[i][j1]-=(a[i][j]/a[j][j])*a[j][j1]; 一句中a[i][j]是零,這樣後面的a[i][j1]全部都將是原來的數值,不會變化,導致錯誤。
2)對於列主元素消元法,個人感覺將a,b兩個矩陣,放在一個矩陣中進行編程,較方便。
第三題:三次樣條插值求近似值
1.解題理論依據或方法應用條件:
依據三彎矩插值法列出相應的方程,然後將x的值帶入在求解三彎矩方程的參數時,應用追趕法求解方程組求出相應參數值)。
2.計算程序使用軟件:VC):
#include<stdio.h>
#include<math.h>
main()
{ int i;
double s,z; /*定義函數近似值,導數近似值*/
double b[11]={0,2,2,2,2,2,2,2,2,2,2},p[11],g[11],l[11]; /*追趕法中變量b,β,δ,l*/
double m[11]={0,0,0,0,0,0,0,0,0,0,0};
doublef[11]={0,0,0.69314718,1.0986123,1.3862944,1.6094378,1.7917595,1.9459101,2.079445,2.1972246,2.3025851}; /*原插值點對應函數值*/
double y[11]={0,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,1}; /*變量η*/
double x[10]={0,1,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5}; /*變量λ*/
doubled[11]={0,6*(f[2]-1),3*(f[3]+f[1]-2*f[2]),3*(f[4]+f[2]-2*f[3]),3*(f[5]+f[3]-2*f[4]),3*(f[6]+f[4]-2*f[5]),3*(f[7]+f[5]-2*f[6]),3*(f[8]+f[6]-2*f[7]),3*(f[9]+f[7]-2*f[8]),3*(f[10]+f[8]-2*f[9]),6*(0.1-f[10]+f[9])};
p[1]=2;g[1]=d[1];
for(i=1;i<=9;i++)
{l[i+1]=y[i]/p[i];
p[i+1]=b[i+1]-l[i+1]*x[i];
g[i+1]=d[i+1]-l[i+1]*g[i];} /*求出追趕法中相應參數*/
m[10]=g[10]/p[10];
for(i=9;i>=1;i--)
m[i]=(g[i]-x[i]*m[i+1])/p[i]; /*應用追趕法求出最終方程解*/
s=m[4]*pow(5-4.563,3)/6+m[5]*pow(4.563-4,3)/6+(f[4]-m[4]/6)*(5-4.563)+(f[5]-m[5]/6)*(4.563-4);
z=-m[4]/2*pow(5-4.563,2)+m[5]/2*pow(4.563-4,2)-(f[4]-m[4]/6)+(f[5]-m[5]/6);
printf("函數f(4.563)近似值 :%.16lf\n導數f'(4.563)近似值:%.16lf\n",s,z);
/*求出函數值和導數值並輸出*/}
3.計算結果
1)在做數組相關的編程時,特別注意下標的使用,因為數組下標是從0開始的,以後可以統一將下標為0的數組位置置0,從下標為1的位置開始賦值使用。
2)編程的過程出現問題如下:①第二個for循環i--誤寫成i++,造成無限循環錯誤②在乘法的運算中漏掉了兩個小括號間的“×”號
本文出自 “馬凱的技術博客” 博客,請務必保留此出處http://makai.blog.51cto.com/2205493/496806