从一泓学长那里改写的我是链接
- (25分)计算积分
, n=0,1,2,…,20
若用下列两种算法
(A)
(B)
试依据积分In的性质及数值结果说明何种算法更合理。
public class TaskOne {
public static void main(String[] args) {
double i = 0.18232155679395; //ln6 - ln5
System.out.println("算法A:");
System.out.println("I(0)=0.18232155679395");
for (int m = 1; m <= 20; m++) {
i = -5*i+Math.pow(m,-1);
System.out.println("I("+m+")="+i);
}
double j = 0.007997523028232166;
System.out.println("算法B:");
for (int n = 20; n >= 0 ; n--) {
System.out.println("I("+n+")="+j);
j = 0.2*(Math.pow(n,-1)-j);
}
}
}
打印结果:
算法A:
I(0)=0.18232155679395
I(1)=0.08839221603024994
I(2)=0.058038919848750314
I(3)=0.04313873408958174
I(4)=0.034306329552091286
I(5)=0.028468352239543582
I(6)=0.02432490546894875
I(7)=0.021232615512399106
I(8)=0.018836922438004472
I(9)=0.016926498921088745
I(10)=0.01536750539455628
I(11)=0.014071563936309511
I(12)=0.012975513651785772
I(13)=0.012045508664148066
I(14)=0.011201028107831093
I(15)=0.0106615261275112
I(16)=0.009192369362443997
I(17)=0.012861682599544719
I(18)=-0.008752857442168041
I(19)=0.09639586615820862
I(20)=-0.4319793307910431
算法B:
I(20)=0.007997523028232166
I(19)=0.008400495394353568
I(18)=0.00884621671060297
I(17)=0.009341867768990517
I(16)=0.009896332328554839
I(15)=0.010520733534289034
I(14)=0.011229186626475526
I(13)=0.01203987696041918
I(12)=0.01297663999253155
I(11)=0.014071338668160356
I(10)=0.015367550448186114
I(9)=0.01692648991036278
I(8)=0.01883692424014967
I(7)=0.02123261515197007
I(6)=0.024324905541034558
I(5)=0.02846835222512642
I(4)=0.03430632955497472
I(3)=0.04313873408900506
I(2)=0.05803891984886566
I(1)=0.08839221603022687
I(0)=0.18232155679395465
分析:算法A每向前计算一步,其舍入误差便增大5倍,算法B每向前计算一步其舍入误差便减小5倍,所以算法B更合理一些。
- (25分)求解方程f(x)=0有如下牛顿迭代公式
, n≥1,x0给定
(1) 编制上述算法的通用程序,并以 (ε为预定精度)作为终止迭代的准则。
(2) 利用牛顿迭代求解方程
设预定精度ε=10-10。
% newton:
function [x1,k] = newton(f,f_de,varible,x0,eplison)
dx = -subs(f_de,varible,x0)\subs(f,varible,x0);
x1=x0+dx;
k=1;
while norm(x1-x0)>=eplison
x0=x1;
dx=-subs(f_de,varible,x0)\subs(f,varible,x0);
x1=x0+dx;
k=k+1;
end
end
format short
syms x y
f1=5*cos(x)-x*y-3;
f2=y^2+8*x*y-7;
F=[f1;f2];
F_de=[diff(F,'x'),diff(F,'y')];
eplison=10e-10;
variable=[x;y];
X0=[1;1];
[x,k]=newton(F,F_de,variable,X0,eplison);
for i=1:length(x)
fprintf('%1.6f\n',x(i));
end
打印结果:
0.724712
1.025858
- (25分) 已知 ,
(1) 利用插值节点x0=1.00,x1=1.02,x2=1.04,x3=1.06,构造三次Lagrange插值公式,由此计算f(1.03)的近似值,并给出其实际误差;
(2) 利用插值节点x0=1,x1=1.05构造三次Hermite插值公式,由此计算f(1.03)的近似值,并给出其实际误差。
public class TaskThree {
public static void main(String[] args) {
double x = 1.03;
double almost = f(x);
System.out.println("Lagrange插值方法:");
System.out.printf("估计为:f(%f)=%f\n",x,almost);
double error = Math.abs(almost-fx(1.03));
System.out.println("实际误差为:"+error);
System.out.println("Hermite插值方法:");
TaskThree taskThree = new TaskThree();
taskThree.calculate();
}
public static double f(double x)
{
double result =((x-1.02)*(x-1.04)*(x-1.06))/((1.00-1.02)
*(1.00-1.04)*(1.00-1.06))*fx(1.00)+
((x-1.00)*(x-1.04)*(x-1.06))/((1.02-1.00)
*(1.02-1.04)*(1.02-1.06))*fx(1.02)+
((x-1.00)*(x-1.02)*(x-1.06))/((1.04-1.00)
*(1.04-1.02)*(1.04-1.06))*fx(1.04)+
((x-1.00)*(x-1.02)*(x-1.04))/((1.06-1.00)
*(1.06-1.02)*(1.06-1.04))*fx(1.06);
return result;
}
public static double fx(double x){
return Math.pow(Math.E,x)*(3*x-Math.pow(Math.E,x));
}
double L1(double x){
return (x-1.02)*(x-1.05)/((1.00-1.02)*(1-1.05));
}
double L2(double x){
return (x-1.00)*(x-1.05)/((1.02-1.00)*(1.02-1.05));
}
double L3(double x){
return (x-1.00)*(x-1.02)/((1.05-1.00)*(1.05-1.02));
}
double a1(double x){
return (1-2.0*(x-1.00)*(-70.0))*Math.pow(L1(x),2.0);
}
double a2(double x){
return (1-2.0*(x-1.02)*(50.0/3.0))*Math.pow(L2(x),2.0);
}
double a3(double x){
return (1-2.0*(x-1.05)*(160/3))*Math.pow(L3(x),2.0);
}
double belta1(double x){
return (x-1.00)*Math.pow(L1(x),2.0);
}
double belta2(double x){
return (x-1.02)*Math.pow(L2(x),2.0);
}
double belta3(double x){
return (x-1.05)*Math.pow(L3(x),2.0);
}
double H3(double x){
double y1,y2,y3,derivative_y1,derivative_y2,derivative_y3;
y1=0.7657893864464859;
y2=0.7953667788517541;
y3=0.8354311093313167;
derivative_y1=1.5315787728929717;
derivative_y2=1.4243418718656515;
derivative_y3=1.242214550953158;
double result = y1*a1(x)+y2*a2(x)+y3*a3(x)+derivative_y1*belta1(x)+derivative_y2*belta2(x)+derivative_y3*belta3(x);
return result;
}
void calculate(){
double x = 1.03;
System.out.printf("估计为:f(%f)=%f\n",x,H3(x));
System.out.println("实际误差为:"+Math.abs(H3(x)-fx(1.03)));
}
}
输出结果:
Lagrange插值方法:
估计为:f(1.030000)=0.809324
实际误差为:3.123082640277275E-7
Hermite插值方法:
估计为:f(1.030000)=0.808878
实际误差为:4.455632364197548E-4
- (25分) 利用复合求积算法计算积分
取步长为10-4
使用复合辛普森公式:
%% algorithm:
function F = algorithm(f,a,b,h)
N=(b-a)/h;
f_sum_half=0;
f_sum=0;
x_n=a;
for n=1:N-1
x_n_half=x_n+h/2;
x_n=a+n*h;
f_sum_half=f_sum_half+f(x_n_half);
f_sum=f_sum+f(x_n);
end
F=h/6*(f(a)+4*f_sum_half+2*f_sum+f(b));
end
syms x
g(x)=sqrt(1+cos(x)^2);
a=0;
b=48;
% h=10e-4;
h=0.1;
F_algorithm=algorithm(g,a,b,h);
fprintf('结果为:%1.6f\n', F_algorithm);
打印结果为:
结果为:58. 462540