数值计算方法

数值计算方法知识面涉及微积分,线性代数;运用编程的方法来解决关于数值计算的问题,其中重点讨论如何最小化误差,一些方程的数值解法,以及插值和拟合问题。其中的知识可以作为数据挖掘的基础。

原文链接 https://blog.gongyan.me/2017/04/shu-zhi-ji-suan-fang-fa/ 转载请注明,有问题欢迎联系我 gongyanc@outlook.com

习题0

执行>> 5.1-5-0.1和>> 1.5-1-0.5,给出执行结果,并简要分析一下产生现象的原因

代码:

>>x1=5.1-5-0.1
>>x1=
>>-3.608224830031759e-16
>>x2=1.5-1-0.5
>>x2=
>>0

原因:

浮点数表示时数字时位数有限,以双精度浮点数为例,共64位。
对于5.1,符号位一位,指数位11,整数部分占3位,小数部分0.1不能精确表示只能近似用49位表示。5.1-5-0.1,5被精确表示,0.1则用52位近似表示。故5.1中的小数部分0.1在计算机中比0.1小,最后结果为负。而x2=1.5-1-0.5中,所有的数都被精确表示了,故其结果为0.

习题1

设$I_n = \int_0^1 \frac{x^n}{5+x} dx$
(1) 从$I_0$尽可能精确的近似值出发,利用递推式$I_n = -5I_{n-1} + \frac{1}{n}\ \ \ \ (n = 1, 2, 3, ... ,20)$,计算$I_{20}$的近似值;
(2) 从$I_{20}$较粗糙的估计值出发,利用递推式$I_{n-1} = -\frac{1}{5}I_n + \frac{1}{5n}\ \ \ \ (n = 20, 19, ... , 1)$计算$I_0$的近似值;
(3) 分析结果的可靠性以及出现这种现象的原因.

(1)

(一) 程序设计

1 算法

$$I_n = -5I_{n-1} + \frac{1}{n} \ \ \ \ (n = 1, 2, 3, ... , 20)$$

2 说明事项
  • $I_0$必须取得精确值,利用$I_n = \int_0^1 \frac{x^n}{5+x} dx$计算$I_0$时,会得到ln6-ln5,此处两数相近不宜相减,应换成ln(6/5)
  • 计算出$I_0$后利用循环即可计算出$I_{20}$

(二) 源程序

MATLAB:

function [ y ] = test1_1( n )
y=log(1.2);
for i=1:1:n
    y=-5*y+1/i;
end

Python:

import math

def test1_1(n):
    y = math.log(1.2, math.e)
    for i in range(1, n+1, 1):
        y = -5 * y + 1 / i
    print("%e" % y)

if __name__ == "__main__":
    test1_1(20)

(三) 实验结果

>> test1_1(20)
>> ans =
    4.242637044921560e-03

(2)

(一) 程序设计

1 算法

$$I_{n-1} = -\frac{1}{5}I_n + \frac{1}{5n} \ \ \ \ (n = 20, 19, ... , 1)$$

2 说明事项
  • 将上一题中的结果去除尾数变为4.0e-03,得到$I_{20}$粗糙估计值
  • 计算出$I_{20}$后利用循环即可计算出$I_0$

(二) 源程序

function [ y ] = test1_2
y=4.0e-03;
for i=20:-1:1;
    y=y/(-5)+1/(5*i);
end

(三) 实验结果

>> test1_2
>> ans =
    1.823215567939546e-01

与log(1.2)的值相同

(3)

对于第一个公式
$$I_n = -5I{n-1} + \frac{1}{n}\ \ \ \ (n = 1, 2, 3, ... , 20)$$
分析其误差传递
$$\varepsilon(I^_n) = |I_n - I^n| = -5|I - I^_{n-1}| = (-5)^{20} \varepsilon(I^0)$$
20次之后其误差惊人,其结果不可取
对于第二个公式
$$I
= -\frac{1}{5}I_n + \frac{1}{5n} \ \ \ \ (n = 20, 19, ... , 1)$$
分析其误差传递
$$\varepsilon(I^{n-1}) = |I - I^_{n-1}| = -\frac{1}{5}|I_n - I^_n| = (-\frac{1}{5})^{20} \varepsilon(I^_N)$$
20次之后误差很小

习题2

用下列方法求方程$e^x + 10x - 2 = 0$的近似根,要求误差不超过$\frac{1}{2} \times 10^-3$,并比较计算量
(1) 在区间[0, 1]上用二分法;
(2) 取初值$x_0 = 0$并用迭代过程$x_{k+1} = \frac{2-e^{x_k}}{10}\ \ \ \ (k = 0, 1, 2, ...)$;
(3) 取初值$x_0 = 0$用牛顿法.

(1)

(一) 程序设计

1 算法

二分法通过缩短短区间,一步步逼近方程的根

2 说明事项

此代码只适用于本程序

(二) 源程序

function [ x ] = test2_1
a=0;
b=1;
i=1;
while 1 
    x=(a+b)/2;
    fa=exp(a)+10*a-2;
    fb=exp(b)+10*b-2;
    fx=exp(x)+10*x-2;
    if (abs(fa-fb)<1e-3);
        break;
    end
    if (fa*fx>0)
        a=x;
    else
        b=x;
    end
    i++;
end
i

(三) 试验结果

>>test2_1
>>i=1.50000000000000e+001
>>ans=9.05456542968750e-002

(2)

(一) 程序设计

1 算法

迭代公式$x_{k+1} = \frac{2-e^{x_k}}{10}\ \ \ \ (k = 0, 1, 2, ...)$

(二) 源程序

function [ y ] = fun2_1( x )
y=x;
i=1;
while 1 
    y1=y;
    y=0.1*(2-exp(y1));
    if (abs(y-y1)<5e-4)
        break;
    end
    i++;
end
i

(三) 试验结果

>>test2_2(0)
>>i=4.00000000000000e+000
>>ans=9.05126166743651e-002

(3)

(一) 程序设计

1 算法

牛顿迭代公式$x_{k+1} = x_k - \frac{x_k}{f'(x_k)}$

2 说明事项
  • 对于定义的函数f(x), 为了方便计算,我们用数值微分来近似计算一阶导数的值:
    $$f'(x_k) \approx \frac{f(x_k+h) - f(x_k)}{h}$$
    其中h是预先取定的小步长;
  • 因为计算公式中有除法,必须对除数为0的情况作异常处理.

(二) 源程序

function [ y ] = fun2_3( x )
y=x;
i=1;
while 1 
    y1=y;
    y=y1-(exp(y1)+10*y1-2)/(exp(y1)+10);
    if (abs(y-y1)<5e-4)
        break;
    end
    i++;
end
i

(三) 试验结果

>>test2_3(0)
>>i=2.00000000000000e+000    %i为迭代次数
>>ans=9.05251085833896e-002  %ans为根
posted @ 2017-04-13 13:40  龚焱  阅读(2430)  评论(0编辑  收藏  举报