实验一舍入误差与数值稳定性
用两种不同的顺序计算≈1.644834,分析其误差的变化;
程序:
#include<stdio.h>
#include<math.h>
void main()
{
int i;
float sum_0=0,sum_1=0;
for(i=1;i<10001;i++)
sum_0+=1.0/(i*i);
printf("%f\n",sum_0);
for(i=10000;i>0;i--)
sum_1+=1.0/(i*i);
printf("%f\n",sum_1);
}
输出:
sum_0=1.644725
sum_1=1.644834
分析讨论:
在计算机内作加法运算时,首先要对加数作对阶处理。由于加数和被加数相比是一个小量,加之计算机字长有限,加数被作为机器零处理了,与被加数相加实际上是被被加数“吃掉”了。
因此多个数相加,应按绝对值从小到大的顺序依次相加,可以保留更多的有效位数。
实验二 方程求根——二分法
一、目的和要求
1)通过对二分法的编程练习,掌握方程求根的二分法的算法;
2)通过对二分法的上机运算,进一步体会二分法的特点。
二、实习内容
1)二分法的编程实现。
2)进行有根区间和误差限的比较和讨论。
三、算法
流程图:
1)准备:计算f(x)在有根区间[a, b]端点处的值 f(a), f(b)。
2)二分:计算f(x)在区间中点c=处的函数值f(c)。
3)判断
? 若f(c)与f(a)异号,则根位于区间[a, c]内,以c代替b;
? 若f(c)与f(a)同号,则根位于区间[c, b]内,以c代替a;
四、实验步骤
1)完成二分法的程序设计及录入;
2)完成程序的编译和链接,并进行修改;
3)用书上的例子对程序进行验证,并进行修改;
4)对比估算次数与实际二分次数;
5)输入不同的区间初值a, b,查看二分次数的变化;
6)输入不同的误差限,查看二分次数的变化;
7)完成实验报告。
五、实验结果
1. 经编译、链接及例子验证结果正确的源程序:
#include<stdio.h>
#include<math.h>
#define eps 5e-4
#define delta 1e-6
float f(float x)
{
return x*x*x+x*x-3*x-3;
}
void main()
{
float a,b,c;
int k;
float fa,fb,fc;
int n=1;
scanf("%f,%f",&a,&b);
printf("a=%f b=%f\n",a,b);
k=(log(b-a)-log(eps))/log(2.0);
printf("k=%d\n",k);
fa=f(a);
fb=f(b);
do
{
if(fa*fb>0)
{
printf("无解");
break;
}
else
{
c=(a+b)/2;
fc=f(c);
if(fabs(fc)<delta)break;
if(fa*fc<0)
{
b=c;
fb=fc;
}
if(fb*fc<0)
{
a=c;
fa=fc;
}
if((b-a)<eps)break;
}
printf("%d %f %f\n",n,c,fc);
n++;
}
while(n=k );
}
2. 实例验证结果:
1)方程:f(x)=x3+x2-3x-3=0
2)输入初始参数:a=1, b=2, EPS=5e-6
3)结果输出:
3. 改变a, b的值为:a=0, b=2, EPS不变,仍为5e-6,其结果为:
4. 改变EPS的值为:EPS=5e-4, a, b不变,仍为a=1, b=2,其结果为:
六、分析和讨论
1. 估算次数与实际二分次数的分析和讨论
答:估算的次数与实际二分次数相等,即估算多少次,就二分了多少次.
2. 输入不同的区间初值a, b,二分次数的变化情况
答:输入的区间范围越大,要达到相同的精确值,二分次数K会相应的增加。
3. 输入不同的误差限EPS,二分次数的变化情况
答:随着误差限的增大,二分次数会相应的减少
七、心得
通过二分计算在电脑中的演示更一步了解了二分法的特点: 用对分区间的方法根据分点处函数f(x)值的符号逐步将有根区间缩小,使在足够小的区间内,方程有且仅有一个根. 二分法收敛速度较慢,在编程过程中,对变量的定义采用哪种类型,主要是对条件的判断做准确分析,对中断条件的准确把握,在调试过程中,对k值采用哪种类型的定义,对k值的输出有很大关系。
第二篇:计算方法数值实验报告
计算方法数值实验报告(一)
班级:0902 学生:苗卓芳 倪慧强 岳婧
实验名称: 解线性方程组的列主元素高斯消去法和LU分解法
实验目的: 通过数值实验,从中体会解线性方程组选主元的必要性和LU分解法的优点,以及方程组系数矩阵和右端向量的微小变化对解向量的影响。
实验内容:解下列两个线性方程组
(1)
(2)
解:(1) 用熟悉的算法语言编写程序用列主元高斯消去法和LU分解求解上述两个方程组,输出Ax=b中矩阵A及向量b, A=LU分解的L及U,detA及解向量。
①先求解第一个线性方程组
在命令窗口中运行A=[3.01,6.03,1.99;1.27,4.16,-1.23;0.987,-4.81,9.34]
可得A =
3.0100 6.0300 1.9900
1.2700 4.1600 -1.2300
0.9870 -4.8100 9.3400
b=[1,1,1]
可得b =
1 1 1
H =det(A)
可得 H =
-0.0305
列主元高斯消去法:
在命令窗口中运行function x=Gauss_pivot(A,b)、A=[3.01,6.03,1.99;1.27,4.16,-1.23;0.987,-4.81,9.34];
b=[1,1,1];
n=length(b);
x=zeros(n,1);
c=zeros(1,n);
dl=0;
for i=1:n-1
max=abs(A(i,i));
m=i;
for j=i+1:n
if max<abs(A(j,i))
max=abs(A(j,i));
m=j;
end
end
if(m~=i)
for k=i:n
c(k)=A(i,k);
A(i,k)=A(m,k);
A(m,k)=c(k);
end
dl=b(i);
b(i)=b(m);
b(m)=dl;
end
for k=i+1:n
for j=i+1:n
A(k,j)=A(k,j)-A(i,j)*A(k,i)/A(i,i);
end
b(k)=b(k)-b(i)*A(k,i)/A(i,i);
A(k,i)=0;
end
end
x(n)=b(n)/A(n,n);
for i=n-1:-1:1
sum=0;
for j=i+1:n
sum =sum+A(i,j)*x(j);
end
x(i)=(b(i)-sum)/A(i,i);
end
经程序可得实验结果
ans =
1.0e+003 *
1.5926
-0.6319
-0.4936
LU分解法:
在命令窗口中运行 function x=lu_decompose(A,b) A=[3.01,6.03,1.99;1.27,4.16,-1.23;0.987,-4.81,9.34];
b=[1,1,1];
L=eye(n);
U=zeros(n,n);
x=zeros(n,1);
c=zeros(1,n);
for i=1:n
U(1,i)=A(1,i);
if i==1;
L(i,1)=1;
else
L(i,1)=A(i,1)/U(1,1);
end
end
for i=2:n
for j=i:n
sum=0;
for k=1:i-1
sum =sum+L(i,k)*U(k,j);
end
U(i,j)=A(i,j)-sum;
Ifj~=n
sum=0;
for k=1:i-1
sum=sum+L(j+1,k)*U(k,i);
end
L(j+1,i)=(A(j+1,i)-sum)/U(I,i);
end
end
end
y(1)=b(1);
for k=2:n
sum=0;
forj=1:k-1
sum=sum+L(k,j)*y (j);
end
y(k)=b(k)-sum;
end
x(n)=y(n)/U(n,n);
260页最后一行
c(k)=A(i,k);
A(i,k)=A(m,k);
A(m,k)=c(k);
end
dl=b(i);
b(i)=b(m);
b(m)=dl;
end
for k=i+1:n
for j=i+1:n
A(k,j)=A(k,j)-A(i,j)*A(k,i)/A(i,i);
end
b(k)=b(k)-b(i)*A(k,i)/A(i,i);
A(k,i)=0;
end
end
x(n)=b(n)/A(n,n);
for i=n-1:-1:1
sum=0;
for j=i+1:n
sum =sum+A(i,j)*x(j);
end
x(i)=(b(i)-sum)/A(i,i);
end
经程序可得结果
ans =
1.0e+003 *
1.5926
-0.6319
-0.4936
②再求解第二个线性方程组
即A=[10,-7,0,1;-3,2.099999,6,2;5,-1,5,-1;2,1,0,2];
b=[8,5.900001,5,1];
重复上述步骤可的结果为
ans =
0.0000
-1.0000
1.0000
1.0000
(2)将方程组(1)中系数3.01改为3.00,0.987改为0.990,用列主元高斯消去法求解变换后的方程组,输出列主元行交换次序,解向量x及detA,并与(1)中结果比较。
先将方程组(1)中系数3.01改为3.00,0.987改为0.990,即A=[3.00,6.03,1.99;1.27,4.16,-1.23;0.990,-4.81,9.34];
b=[1,1,1];
在命令窗口中运行A=[3.00,6.03,1.99;1.27,4.16,-1.23;0.990,-4.81,9.34]
可得A =
3.0000 6.0300 1.9900
1.2700 4.1600 -1.2300
0.9900 -4.8100 9.3400
H=det(A)
可得H =
-0.4070
用列主元高斯消去法求解变换后的方程组,可得
ans =
119.5273
-47.1426
-36.8403
(3) 将方程组(2)中的2.099999改为2.1,5.900001改为5.9,用列主元高斯消去法求解变换后的方程组,输出解向量x及detA,并与(1)中的结果比较。
先将方程组(2)中的2.099999改为2.1,5.900001改为5.9,即A=[10,-7,0,1;-3,2.1,6,2;5,-1,5,-1;2,1,0,2];
b=[8,5.9,5,1];
用列主元高斯消去法求解变换后的方程组,输出解向量x
可得ans =
-0.0000
-1.0000
1.0000
1.0000
H=det(A)
可得H =
-762.0000
(4)用MATLAB的内部函数inv求出系数矩阵的逆矩阵,再输入命令x=inv(A)*b,即可求出上述各个方程组的解,并与列主元高斯消去法和LU分解法求出的解进行比较,体会选主元的方法具有良好的数值稳定性。用MATLAB的内部函数det求出系数行列式的值,并与(1)、(2)、(3)中输出的系数行列式的值进行比较。
在命令窗口中运行
A=[3.01,6.03,1.99;1.27,4.16,-1.23;0.987,-4.81,9.34];
ni=inv(A)
可得ni =
1.0e+003 *
-1.0783 2.1571 0.5138
0.4281 -0.8560 -0.2039
0.3344 -0.6688 -0.1592
实验要求:
(1) 用你熟悉的算法语言编写程序用列主元高斯消去法和LU分解求解上述两个方程组,输出Ax=b中矩阵A及向量b, A=LU分解的L及U,detA及解向量x.
(2) 将方程组(1)中系数3.01改为3.00,0.987改为0.990,用列主元高斯消去法求解变换后的方程组,输出列主元行交换次序,解向量x及detA,并与(1)中结果比较。
(3) 将方程组(2)中的2.099999改为2.1,5.900001改为5.9,用列主元高斯消去法求解变换后的方程组,输出解向量x及detA,并与(1)中的结果比较。
(4)用MATLAB的内部函数inv求出系数矩阵的逆矩阵,再输入命令x=inv(A)*b,即可求出上述各个方程组的解,并与列主元高斯消去法和LU分解法求出的解进行比较,体会选主元的方法具有良好的数值稳定性。用MATLAB的内部函数det求出系数行列式的值,并与(1)、(2)、(3)中输出的系数行列式的值进行比较。