├── 数值计算方法.xmind ├── 第一章 引论 ├── 引论.xmind ├── ch01_1.pdf ├── ch01_2.pdf ├── Matlabcmd.pdf ├── MatlabTutorial2007.pdf ├── demo_1_1.m ├── demo_1_3.m ├── example_0_2.m └── demo_1_2.m ├── 实验 ├── 拉格朗日插值算法框图.JPG ├── 梯形法递推算法框图.JPG ├── 龙贝格积分算法框图.JPG └── 《数值计算方法》实验指导书.doc ├── 第三章 函数逼近 ├── ch03.pdf ├── demo32.m ├── nest.m ├── demo33.m ├── d_d.m ├── demo31.m └── demo_3_0.m ├── 第二章 插值方法 ├── ch02_1.pdf ├── ch02_2.pdf ├── ch02_3.pdf ├── ch02_4.pdf ├── ch02_5.pdf ├── ch02_6.pdf ├── 插值法.xmind ├── demo_2_2.m ├── example_2_2.m ├── my_log.m ├── d_q.m ├── application_2_4.m ├── demo_2_9.m ├── example_2_3.m ├── nest.m ├── example_2_5.m ├── my_sin.m ├── d_d.m ├── demo_2_10.m ├── application_2_3.m ├── demo_2_4.m ├── application_2_2.m ├── demo_2_3.m ├── demo_2_1.m ├── demo_2_14.m ├── demo_2_13.m ├── demo_2_8.m ├── bezier.m ├── example_2_6.m ├── demo_2_5.m ├── application_2_1.m ├── application_2_5.m ├── demo_2_12.m ├── demo_2_11.m ├── demo_2_0.m ├── demo_2_6.m └── demo_2_7.m ├── 第四章 数值积分 ├── ch04_1.pdf ├── ch04_2.pdf ├── ch04_3.pdf ├── ch04_4.pdf ├── 数值积分.xmind ├── demo_4_8.m ├── demo_4_2.m ├── demo_4_1.m ├── gaussquad.m ├── demo_4_3.m ├── application_4_1.m ├── lagrange_interp.m ├── gausscoef.m ├── demo_4_9.m ├── demo_4_5.m ├── demo_4_10.m ├── quadgui_simpson.m ├── demo_4_7.m ├── demo_4_0.m ├── application_4_2.m ├── demo_4_4.m ├── demo_4_6.m └── quadgui_adaptive.m ├── 第七章 非线性方程解法 ├── ch07_1.pdf ├── ch07_2.pdf ├── 非线性方程解法.xmind ├── demo_7_1.m ├── demo_7_7.m ├── demo_7_2.m ├── demo_7_8.m ├── demo_7_10.m ├── demo_7_3.m ├── demo_7_5.m ├── demo_7_6.m ├── demo_7_9.m └── demo_7_4.m ├── 第五章 线性方程组直接解法 ├── ch05_1.pdf ├── ch05_2.pdf ├── ch05_3.pdf ├── 线性方程组的直接法.xmind ├── demo_5_4.m ├── demo_5_1.m ├── demo_5_2.m ├── demo_5_5.m ├── demo_5_3.m ├── my_ge.m ├── my_cholesky.m ├── my_ge_with_column_pivoting.m ├── my_lu.m ├── my_forward_backward.m ├── my_doolittle.m ├── my_lu_with_column_pivoting.m └── lugui.m └── 第六章 线性方程组迭代解法 ├── ch06_1.pdf ├── ch06_2.pdf ├── 线性方程组的迭代法.xmind ├── demo_6_2.m ├── example_6_1_a.m ├── example_6_2_a.m ├── demo_6_1.m ├── example_6_3_a.m ├── example_6_2.m ├── example_6_1.m ├── example_6_3.m └── demo_6_3.m /数值计算方法.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/数值计算方法.xmind -------------------------------------------------------------------------------- /第一章 引论/引论.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第一章 引论/引论.xmind -------------------------------------------------------------------------------- /实验/拉格朗日插值算法框图.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/实验/拉格朗日插值算法框图.JPG -------------------------------------------------------------------------------- /实验/梯形法递推算法框图.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/实验/梯形法递推算法框图.JPG -------------------------------------------------------------------------------- /实验/龙贝格积分算法框图.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/实验/龙贝格积分算法框图.JPG -------------------------------------------------------------------------------- /第一章 引论/ch01_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第一章 引论/ch01_1.pdf -------------------------------------------------------------------------------- /第一章 引论/ch01_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第一章 引论/ch01_2.pdf -------------------------------------------------------------------------------- /第三章 函数逼近/ch03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第三章 函数逼近/ch03.pdf -------------------------------------------------------------------------------- /实验/《数值计算方法》实验指导书.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/实验/《数值计算方法》实验指导书.doc -------------------------------------------------------------------------------- /第一章 引论/Matlabcmd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第一章 引论/Matlabcmd.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_1.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_2.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_3.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_4.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_5.pdf -------------------------------------------------------------------------------- /第二章 插值方法/ch02_6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/ch02_6.pdf -------------------------------------------------------------------------------- /第二章 插值方法/插值法.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第二章 插值方法/插值法.xmind -------------------------------------------------------------------------------- /第四章 数值积分/ch04_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第四章 数值积分/ch04_1.pdf -------------------------------------------------------------------------------- /第四章 数值积分/ch04_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第四章 数值积分/ch04_2.pdf -------------------------------------------------------------------------------- /第四章 数值积分/ch04_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第四章 数值积分/ch04_3.pdf -------------------------------------------------------------------------------- /第四章 数值积分/ch04_4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第四章 数值积分/ch04_4.pdf -------------------------------------------------------------------------------- /第四章 数值积分/数值积分.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第四章 数值积分/数值积分.xmind -------------------------------------------------------------------------------- /第七章 非线性方程解法/ch07_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第七章 非线性方程解法/ch07_1.pdf -------------------------------------------------------------------------------- /第七章 非线性方程解法/ch07_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第七章 非线性方程解法/ch07_2.pdf -------------------------------------------------------------------------------- /第七章 非线性方程解法/非线性方程解法.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第七章 非线性方程解法/非线性方程解法.xmind -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/ch05_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第五章 线性方程组直接解法/ch05_1.pdf -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/ch05_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第五章 线性方程组直接解法/ch05_2.pdf -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/ch05_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第五章 线性方程组直接解法/ch05_3.pdf -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/ch06_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第六章 线性方程组迭代解法/ch06_1.pdf -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/ch06_2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第六章 线性方程组迭代解法/ch06_2.pdf -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_2.m: -------------------------------------------------------------------------------- 1 | % 计算各阶差商 2 | clear; clc; 3 | x = [-2,-1,1,2]; 4 | y = [5,3,17,21]; 5 | [p,q] = d_d(x,y); 6 | -------------------------------------------------------------------------------- /第一章 引论/MatlabTutorial2007.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第一章 引论/MatlabTutorial2007.pdf -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/线性方程组的直接法.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第五章 线性方程组直接解法/线性方程组的直接法.xmind -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/线性方程组的迭代法.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qxr777/NumericalMethod/HEAD/第六章 线性方程组迭代解法/线性方程组的迭代法.xmind -------------------------------------------------------------------------------- /第二章 插值方法/example_2_2.m: -------------------------------------------------------------------------------- 1 | % p16 例2 线性插值 2 | x = [100, 121]; 3 | y = [10, 11]; 4 | xx = 115; % 插值点 5 | yy = (xx - x(2)) / (x(1) - x(2)) * y(1) + (xx - x(1)) / (x(2) - x(1)) * y(2) -------------------------------------------------------------------------------- /第二章 插值方法/my_log.m: -------------------------------------------------------------------------------- 1 | function [ y ] = my_log( xl ) 2 | %MY_LOG 以插值方法实现自然对数函数 3 | % Detailed explanation goes here 4 | b = 1 : 4; 5 | yb = log(b); 6 | [m, c] = d_d(b, yb); 7 | y = nest(c, xl, b); 8 | end 9 | 10 | -------------------------------------------------------------------------------- /第三章 函数逼近/demo32.m: -------------------------------------------------------------------------------- 1 | % 最小二乘拟合多项式 2 | clear; 3 | 4 | x = [0; 0.25; 0.5; 0.75; 1]; 5 | y = [1; 1.284; 1.6487; 2.117; 2.7183]; 6 | C = [x.^0, x.^1, x.^2]; 7 | A = C' * C; 8 | b = C' * y; 9 | 10 | %a = inv(A)*b 11 | a = A \ b; -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/demo_5_4.m: -------------------------------------------------------------------------------- 1 | % 演示调用 追赶法 分解 2 | clear; 3 | A=[2 -1 0 0; -1 2 -1 0; 0 -1 2 -1; 0 0 -1 2]; %对角占优的三对角矩阵 4 | f=[1;0;0;0]; 5 | 6 | % 追赶分解法 7 | x = my_forward_backward(A, f) 8 | 9 | % 直接调用matlab左除运算符 10 | x_ = A \ f -------------------------------------------------------------------------------- /第一章 引论/demo_1_1.m: -------------------------------------------------------------------------------- 1 | % 秦九韶算法 求多项式的值 2 | clear; 3 | a = [1 2 -12 -1 7]; % 多项式系数,高阶系数在前 4 | x = 3; 5 | n = length(a); 6 | 7 | v = a(1); 8 | for k = 1 : n - 1 9 | v = x * v + a(k + 1); 10 | end 11 | fprintf('多项式求值 计算结果:%f\n',v); 12 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/demo_5_1.m: -------------------------------------------------------------------------------- 1 | % 演示调用 消去法 2 | clear; 3 | A=[1,-2,2; 2,-3,-3; 4,1,6]; 4 | b=[-2;4;3]; 5 | 6 | % 调用 高斯消去法 7 | %x = my_ge(A, b) 8 | 9 | % 调用 列主元高斯消去法 10 | x = my_ge_with_column_pivoting(A, b) 11 | 12 | % 直接调用matlab左除运算符 13 | %x_ = A\b 14 | 15 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/demo_5_2.m: -------------------------------------------------------------------------------- 1 | % 演示调用 LU 分解的紧凑方式 2 | clear; 3 | A=[1,-2,2; 2,-3,-3; 4,1,6]; 4 | b=[-2;4;3]; 5 | 6 | % LU三角分解法 7 | [L, U, x] = my_lu(A, b) 8 | 9 | % 列主元LU三角分解法 10 | %[L, U, x] = my_lu_with_column_pivoting(A, b) 11 | 12 | % 直接调用matlab左除运算符 13 | x_ = A\b -------------------------------------------------------------------------------- /第一章 引论/demo_1_3.m: -------------------------------------------------------------------------------- 1 | % 避免大数吃小数 2 | clear; 3 | 4 | % 计算 (10^9+10^-9-10^9)/10^-9 5 | S = (10^9 + 10^-9 - 10^9) / 10 ^ -9; 6 | fprintf('直接计算的结果为: %.20e\n',S); 7 | % S1 = S; 8 | 9 | % 改变顺序,再次计算 10 | S = (10^9 - 10^9 + 10^-9) / 10 ^ -9; 11 | fprintf('改变顺序计算的结果为: %.20e\n',S); -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/demo_6_2.m: -------------------------------------------------------------------------------- 1 | % 考虑迭代法 x = Bx + f 的收敛性 2 | clear; 3 | 4 | B = [0.9 0; 0.3 0.8]; 5 | 6 | fprintf('B的1范数: %f\n', norm(B, 1)); 7 | fprintf('B的2范数: %f\n', norm(B, 2)); 8 | fprintf('B的无穷范数: %f\n', norm(B, inf)); 9 | 10 | fprintf('B的谱半径: %f\n', max(abs(eig(B)))); -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/demo_5_5.m: -------------------------------------------------------------------------------- 1 | % 解的精度与病态 2 | clear; 3 | 4 | A = [3.021 2.714 6.913; 1.031 -4.273 1.121; 5.084 -5.832 9.155]; 5 | b = [12.648 -2.121 8.407]'; 6 | x1 = A\b 7 | 8 | % 将A(2,2)从-4.273替换为-4.275 9 | A(2,2) = -4.275; 10 | x2 = A\b 11 | 12 | fprintf('系数矩阵A的条件数:%f\n',cond(A)); -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/demo_5_3.m: -------------------------------------------------------------------------------- 1 | % 演示调用 平方根法 分解 2 | clear; 3 | % A=[6 7 5; 7 13 8; 5 8 6]; %对称正定矩阵 4 | % b=[9; 10; 9]; 5 | 6 | A=[9,3,6,3;3,5,2,5;6,2,5,4;3,5,4,18]; %对称正定矩阵 7 | b=[6; 6; 5; 17]; 8 | 9 | % 平方根分解法 10 | [L, x] = my_cholesky(A, b) 11 | 12 | % 直接调用matlab左除运算符 13 | x_ = A\b -------------------------------------------------------------------------------- /第二章 插值方法/d_q.m: -------------------------------------------------------------------------------- 1 | % 计算差商 2 | function dq = d_q(x,y) 3 | % 4 | % 参数说明: 5 | % 输入参数: x 为节点,y 为函数值(注意:向量 x 与向量 y 的长度必须一致) 6 | % 输出参数: 7 | % dq 为差商的值 8 | 9 | m = length(x); 10 | dq = 0; 11 | for k = 1 : m 12 | dq = dq + y(k) / prod(x(k) - x([1 : k - 1, k + 1 : end])); 13 | end 14 | 15 | -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_8.m: -------------------------------------------------------------------------------- 1 | % 演示 自适应积分法 p115 例7 2 | clear; 3 | %f = @(x) 1./x.^2; 4 | f = @humps; 5 | a = 0.2; 6 | b = 1; 7 | tol = 0.02; 8 | 9 | % 调用 自适应积分函数 10 | [I, fcount] = quadgui_adaptive(f, a, b, tol); 11 | 12 | % 调用 复合Simpson积分函数 13 | % [I, fcount] = quadgui_simpson(f, a, b, tol); 14 | 15 | 16 | -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_1.m: -------------------------------------------------------------------------------- 1 | % 二分法求方程近似根 2 | clear; 3 | f = @(x) x ^ 3 - x -1; 4 | a = 1; 5 | b = 1.5; 6 | tol = 0.5e-5; 7 | 8 | y0 = f(a); 9 | while (b - a > tol) 10 | x = (a + b) / 2; 11 | y = f(x); 12 | if (y * y0 > 0) 13 | a = x; 14 | else 15 | b = x; 16 | end 17 | end 18 | x 19 | y -------------------------------------------------------------------------------- /第二章 插值方法/application_2_4.m: -------------------------------------------------------------------------------- 1 | % 利用插值法实现数学函数 2 | clear; clc; 3 | x = 0 : 1 : 5; 4 | fprintf('sin函数值 my_sin函数值 误差\n'); 5 | for k = 1 : length(x) 6 | y = sin(x(k)); 7 | y_star = my_sin(x(k)); 8 | error = abs(y - y_star); 9 | fprintf('%.10d %.10d %.10d\n', y, y_star, error); 10 | end -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_9.m: -------------------------------------------------------------------------------- 1 | % spline 举例 2 | clear; clc; 3 | 4 | xi=[27.7, 28, 29, 30]; % 插值节点 5 | yi=[4.1, 4.3, 4.1, 3.0]; % 节点处的函数值 6 | df0=3.0; dfn=-4.0; % 边界条件 7 | pp=spline(xi,[df0, yi, dfn]); 8 | 9 | xh=27.7:0.1:30; % 需要插值的点 10 | yh=ppval(pp,xh); % 通过插值求得的近似值 11 | plot(xi,yi,'r+',xh,yh,'o-b','LineWidth',1.5,'MarkerSize',12); 12 | -------------------------------------------------------------------------------- /第三章 函数逼近/nest.m: -------------------------------------------------------------------------------- 1 | % 牛顿插值多项式求值 2 | % 输入参数 c 是牛顿插值多项式的系数,也就是差商表的对角线 3 | % 输入参数 x 待插值的自变量取值的向量 4 | % 输入参数 xlist 已知的插值节点 5 | % 输出参数 y 插值结果向量 6 | function y = nest(c, x, xlist) 7 | n = length(c); 8 | result = 0; 9 | item = 1; 10 | for k = 1 : n 11 | result = result + c(k) * item; 12 | item = item .* (x - xlist(k)); % 向量的点乘 13 | end 14 | y = result; -------------------------------------------------------------------------------- /第二章 插值方法/example_2_3.m: -------------------------------------------------------------------------------- 1 | % p18 例3 抛物插值 2 | x = [100, 121, 144]; 3 | y = [10, 11, 12]; 4 | xx = 115; % 插值点 5 | l0 = ((xx - x(2)) * (xx - x(3))) / ((x(1) - x(2)) * (x(1) - x(3))); 6 | l1 = ((xx - x(1)) * (xx - x(3))) / ((x(2) - x(1)) * (x(2) - x(3))); 7 | l2 = ((xx - x(1)) * (xx - x(2))) / ((x(3) - x(1)) * (x(3) - x(2))); 8 | yy = l0 * y(1) + l1 * y(2) + l2 * y(3) -------------------------------------------------------------------------------- /第二章 插值方法/nest.m: -------------------------------------------------------------------------------- 1 | % 牛顿插值多项式求值 2 | % 输入参数 c 是牛顿插值多项式的系数,也就是差商表的对角线 3 | % 输入参数 x 待插值的自变量取值的向量 4 | % 输入参数 xlist 已知的插值节点 5 | % 输出参数 y 插值结果向量 6 | function y = nest(c, x, xlist) 7 | n = length(c); 8 | result = 0; 9 | item = 1; 10 | for k = 1 : n 11 | result = result + c(k) * item; 12 | item = item .* (x - xlist(k)); % 向量的点乘 13 | end 14 | y = result; -------------------------------------------------------------------------------- /第二章 插值方法/example_2_5.m: -------------------------------------------------------------------------------- 1 | % p23 例5 埃特金逐步插值 2 | clear; 3 | format long; 4 | x = 0.3 :0.1 : 0.7; 5 | y = [0.29850, 0.39646, 0.49311, 0.58813, 0.68122]; 6 | xx = 0.462; % 插值点 7 | fij(:,1) = y; 8 | for i = 1 : 3 9 | for j = i+1 : 5 10 | fij(j,i+1) = fij(i,i)*(xx-x(j))/(x(i)-x(j)) + fij(j,i)*(xx-x(i))/(x(j)-x(i)) % 显示中间结果,体现迭代 11 | end 12 | end 13 | fij -------------------------------------------------------------------------------- /第二章 插值方法/my_sin.m: -------------------------------------------------------------------------------- 1 | function [ y ] = my_sin( x ) 2 | %MY_SIN 以插值方法实现正弦函数 3 | % Detailed explanation goes here 4 | b = pi * (0 : 1 : 3) / 6; 5 | yb = sin(b); 6 | [m, c] = d_d(b, yb); 7 | s = 1; 8 | xl = mod(x, 2 * pi); 9 | if xl > pi 10 | xl = 2 * pi - xl; 11 | s = -1; 12 | end 13 | if xl > pi / 2 14 | xl = pi -xl; 15 | end 16 | y = s * nest(c, xl, b); 17 | end 18 | 19 | -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_7.m: -------------------------------------------------------------------------------- 1 | % Newton 迭代法 2 | clear; clc 3 | f = @(x) x.*exp(x)-1; 4 | df = @(x) exp(x)*(1+x); 5 | 6 | % f = @(x) sin(x); 7 | % df = @(x) cos(x); 8 | 9 | n = 10; 10 | tol = 1e-16; 11 | x0 = 0.5; % 初始值 12 | %x0 = 6; % 初始值 13 | for k = 1 : n 14 | x = x0 - f(x0)/df(x0); 15 | fprintf('k=%d, x=%.18f\n',k,x); 16 | if abs(x-x0) tol) 11 | x = (a + b) / 2; 12 | y = f(x); 13 | if (y * y0 > 0) 14 | a = x; 15 | else 16 | b = x; 17 | end 18 | n = n + 1; 19 | end 20 | x; 21 | fprintf(' x = %.10d\n', x); 22 | fprintf('迭代次数: %d\n', n); -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_2.m: -------------------------------------------------------------------------------- 1 | % 不动点迭代法 2 | clear; 3 | tol = 1e-5; 4 | f = @(x) x^3-x-1; 5 | %g = @(x) (x+1)^(1/3); 6 | g = @(x) x^3-1; 7 | 8 | fprintf('迭代函数: g=%s\n',char(g)); 9 | 10 | N = 100; % 设置最大迭代步数 11 | x0 = 1.5; % 迭代初始值 12 | for k = 1 : N 13 | x = g(x0); 14 | fprintf('k=%2d,x=%.4e, f(x)=%.4e\n',k, x, f(x)); 15 | if(abs(x-x0) < tol) break; end; 16 | x0 = x; 17 | end 18 | fprintf('迭代次数: %d\n', k); -------------------------------------------------------------------------------- /第三章 函数逼近/d_d.m: -------------------------------------------------------------------------------- 1 | % 计算差商 2 | function [p, q] = d_d(x,y) 3 | % 4 | % 参数说明: 5 | % 输入参数: x 为节点,y 为函数值(注意:向量 x 与向量 y 的长度必须一致) 6 | % 输出参数: 7 | % p 包含所有差商,即差商表中的所有值 8 | % q 为差商表中对角线的值 9 | 10 | m = length(x); 11 | x = x(:); 12 | p = zeros(m, m+1); 13 | p(:,1) = x; 14 | p(:,2) = y(:); 15 | for k = 3 : m+1 16 | p(k-1:m, k) = diff(p(k-2:m, k-1)) ./ ( x(k-1:m) - x(1:m+2-k) ); 17 | end 18 | q = diag(p(1:m,2:m+1)); 19 | -------------------------------------------------------------------------------- /第二章 插值方法/d_d.m: -------------------------------------------------------------------------------- 1 | % 计算差商 2 | function [p, q] = d_d(x,y) 3 | % 4 | % 参数说明: 5 | % 输入参数: x 为节点,y 为函数值(注意:向量 x 与向量 y 的长度必须一致) 6 | % 输出参数: 7 | % p 包含所有差商,即差商表中的所有值 8 | % q 为差商表中对角线的值 9 | 10 | m = length(x); 11 | x = x(:); 12 | p = zeros(m, m+1); 13 | p(:,1) = x; 14 | p(:,2) = y(:); 15 | for k = 3 : m+1 16 | p(k-1:m, k) = diff(p(k-2:m, k-1)) ./ ( x(k-1:m) - x(1:m+2-k) ); 17 | end 18 | q = diag(p(1:m,2:m+1)); 19 | -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_8.m: -------------------------------------------------------------------------------- 1 | % Newton方法(切线法)利用开方公式求115的平方根 2 | clear; 3 | format long; 4 | tol = 1e-6; 5 | N = 100; 6 | x0 = 10; 7 | c = 115; 8 | phi = @(x) (x + c / x) / 2; % 二次方程对应的牛顿公式 9 | 10 | for k = 1 : N 11 | x1 = phi(x0); 12 | if abs(x1 - x0) < tol 13 | fprintf('迭代次数: %d\n', k); 14 | fprintf('方程的正根: %10.8f\n', x1); 15 | break; 16 | end 17 | x0 = x1; 18 | end 19 | if k == N 20 | fprintf('迭代方法失败\n'); 21 | end -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_10.m: -------------------------------------------------------------------------------- 1 | % 快速弦截法求解方程 2 | clear; 3 | format long; 4 | tol = 1e-5; 5 | N = 100; 6 | x0 = 0.5; 7 | x1 = 0.6; 8 | f = @(x) x^3 - x - 1; %f(x)表达式 9 | 10 | for k = 1 : N 11 | x2 = x1 - f(x1) * (x1 - x0) / (f(x1) - f(x0)); 12 | if abs(x2 - x1) < tol 13 | fprintf('迭代次数: %d\n', k); 14 | fprintf('方程的正根: %10.8f\n', x1); 15 | break; 16 | end 17 | x0 = x1; 18 | x1 = x2; 19 | end 20 | if k == N 21 | fprintf('迭代方法失败\n'); 22 | end -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_3.m: -------------------------------------------------------------------------------- 1 | % 求平方根的收敛速度 2 | 3 | clear; clc 4 | f = @(x) x^2-3; 5 | g1 = @(x) x^2-3+x; 6 | g2 = @(x) x-(x^2-3)/4; 7 | g3 = @(x) 0.5*(x+3/x); 8 | 9 | xt = sqrt(3); % 真解 10 | n = 20; % 设置迭代步数 11 | x0 = 2; % 迭代初始值 12 | x1 = x0; x2 = x0; x3 = x0; 13 | 14 | for k = 1 : n 15 | x1 = g1(x1); 16 | x2 = g2(x2); 17 | x3 = g3(x3); 18 | fprintf('k=%d, err1=%.4e, err2=%.4e, err3=%.4e\n', ... 19 | k, norm(x1-xt), norm(x2-xt), norm(x3-xt)); 20 | end 21 | 22 | -------------------------------------------------------------------------------- /第三章 函数逼近/demo31.m: -------------------------------------------------------------------------------- 1 | % 最小二乘法求一次多项式 2 | clear; 3 | x = [2, 4, 4, 4.6, 5, 5.2, 5.6, 6, 6.6, 7]; 4 | y = [5, 3.5, 3, 2.7, 2.4, 2.5, 2, 1.5, 1.2, 1.2]; 5 | plot(x, y, 'o'); % 样本散点图 6 | 7 | A = [length(x), sum(x); sum(x), sum(x .* x)]; % 法方程系数矩阵 8 | b = [sum(y); sum(x .* y)]; % 法方程常数项 9 | % pa = inv(A)*b; % 左乘逆矩阵,求解法方程 10 | pa = A\b; 11 | 12 | pa = pa(end : -1 : 1); % 多项式系数 13 | px = 0 : 0.01 : 10; % 画直线函数的横坐标 14 | py = polyval(pa, px); % 多项式求值 15 | plot(x, y, 'o', px, py); % 一次多项式拟合结果 16 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_10.m: -------------------------------------------------------------------------------- 1 | % 最小二乘法求一次多项式 2 | clear; 3 | x = [2, 4, 4, 4.6, 5, 5.2, 5.6, 6, 6.6, 7]; 4 | y = [5, 3.5, 3, 2.7, 2.4, 2.5, 2, 1.5, 1.2, 1.2]; 5 | % plot(x, y, 'o'); % 样本散点图 6 | 7 | A = [length(x), sum(x); sum(x), sum(x .* x)]; % 法方程系数矩阵 8 | b = [sum(y); sum(x .* y)]; % 法方程常数项 9 | % pa = inv(A)*b; % 左乘逆矩阵,求解法方程 10 | pa = A\b; 11 | 12 | pa = pa(end : -1 : 1); % 多项式系数 13 | px = 0 : 0.01 : 10; % 画直线函数的横坐标 14 | py = polyval(pa, px); % 多项式求值 15 | plot(x, y, 'o', px, py); % 一次多项式拟合结果 16 | -------------------------------------------------------------------------------- /第二章 插值方法/application_2_3.m: -------------------------------------------------------------------------------- 1 | % 家庭储蓄规律问题 2 | clear;clc; 3 | x=[0.6,1.0,1.4,1.8,2.2,2.6,3.0,3.4,3.8,4 ]; % 月收入,单位:万元 4 | y=[0.08,0.22,0.31,0.4,0.48,0.56,0.67,0.75,0.8,1.0 ]; % 月可储蓄金额,单位:万元 5 | 6 | A = [length(x), sum(x); sum(x), sum(x .* x)]; % 法方程系数矩阵 7 | b = [sum(y); sum(x .* y)]; % 法方程常数项 8 | % pa = inv(A)*b; % 左乘逆矩阵,求解 法方程 9 | pa = A\b; % 左除系数矩阵,求解 法方程 10 | 11 | pa = pa(end : -1 : 1); % 多项式系数 12 | px = 0 : 0.01 : 10; % 画直线函数的横坐标 13 | py = polyval(pa, px); % 多项式求值 14 | plot(x, y, 'o', px, py); % 一次多项式拟合结果 -------------------------------------------------------------------------------- /第一章 引论/demo_1_2.m: -------------------------------------------------------------------------------- 1 | % 近似计算 算法稳定性的演示 2 | clear; 3 | 4 | % 解法一 n从小到大 5 | S0 = 0.182; 6 | S(1) = 1 - 5*S0; 7 | for n = 2 : 8 8 | S(n) = 1/n - 5*S(n-1); 9 | S(n) = vpa(S(n),3); 10 | end 11 | disp('解法一:') 12 | disp(S) 13 | 14 | % 解法二 n从大到小 15 | S(8) = 0.0204; 16 | for n = 8: -1 : 2 17 | S(n-1) = 1/(5*n) - S(n)/5; 18 | S(n-1) = vpa(S(n-1),3); 19 | end 20 | disp('解法二:') 21 | disp(S) 22 | 23 | % 精确值 24 | syms x 25 | for n = 1 : 5 % 8 26 | St(n) = int(x^n/(x+5),0,1); 27 | St(n) = vpa(St(n),3); 28 | end 29 | disp('精确值:') 30 | disp(S) -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/example_6_1_a.m: -------------------------------------------------------------------------------- 1 | % Jacobi 迭代法(矩阵形式)求解方程组 2 | clear; 3 | % 输入值 4 | A = [10, -1, -2; -1, 10, -2; -1, -1, 5]; 5 | b = [7.2; 8.3; 4.2]; 6 | tol = 1e-5; 7 | x = [0; 0; 0]; 8 | 9 | D = diag(diag(A)); % A 的对角线部分 10 | L = D - tril(A); % -L 为 A 的严格下三角部分 11 | U = D - triu(A); % -U 为 A 的严格上三角部分 12 | 13 | for i = 0 : 19 14 | y = D \ ( (L+U)*x + b ); % Jacobi迭代公式(矩阵形式) 15 | if (max(abs(x - y)) < tol) 16 | fprintf('迭代次数: %d\n', i); 17 | fprintf('方程组的根: %10.8f\n', y); 18 | break; 19 | end 20 | x = y; 21 | end -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_2.m: -------------------------------------------------------------------------------- 1 | % 复合公式求数值积分 2 | clear; 3 | format long; 4 | f = @(x) sin(x)./x; % 采用数组运算,使得函数可以作用在向量或矩阵上 5 | a = 0; 6 | b = 1; 7 | n = 8; 8 | h = (b-a)/n; 9 | 10 | X = a : h : b; 11 | Y = f(X); 12 | Y(1) = 1; % y(1)=0/sin(0) 13 | 14 | % 复合梯形公式 15 | Tn = Y(1) + 2*sum(Y(2:n)) + Y(n+1); 16 | Tn = Tn*h/2; 17 | fprintf('复合梯形公式计算的近似值为: %.10f\n', Tn); 18 | 19 | % 复合 Simpson 公式 20 | Sn = Y(1) + Y(n+1) + 4*sum(Y(2:2:n)) + 2*sum(Y(3:2:n-1)); 21 | Sn = Sn*h/3; 22 | fprintf('复合Simpson公式计算的近似值为: %.10f\n', Sn); 23 | 24 | fprintf('精确值为: %.10f\n', quad(f, 0, 1)); -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_1.m: -------------------------------------------------------------------------------- 1 | % Newton-Cotes公式求数值积分 2 | clear; 3 | format long; 4 | f = @(x) sin(x)./x; % 采用数组运算,使得函数可以作用在向量或矩阵上 5 | Ck{1} = [1/2, 1/2]; 6 | Ck{2} = [1/6, 2/3, 1/6]; 7 | Ck{3} = [1/8, 3/8, 3/8, 1/8]; 8 | Ck{4} = [7/90, 16/45, 2/15, 16/45, 7/90]; 9 | Ck{5} = [19/288, 25/96, 25/144, 25/144, 25/96, 19/288]; 10 | 11 | a = 0; 12 | b = 1; 13 | for n = 1 : 5 14 | h = (b - a) / n; 15 | X = 0 : h : 1; 16 | Y = f(X); 17 | Y(1) = 1; % y(1)=0/sin(0) 18 | I(n) = sum(Ck{n} .* Y); 19 | end 20 | I % 1阶到5阶Newton-Cotes求积结果 21 | Im = quad(f, 0, 1) % matlab求积函数 -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_4.m: -------------------------------------------------------------------------------- 1 | % Newton 前插公式 2 | clear; 3 | h = 0.1; 4 | X = 0.0 : h : 0.5; 5 | % Y = [1.00000,0.99500,0.98007,0.95534,0.92106,0.87758]; 6 | Y = cos(X); 7 | 8 | % 计算各阶差分 9 | n = length(X) - 1; 10 | p = zeros(n+1,n+1); 11 | p(:,1) = Y(:); 12 | for k = 1 : n 13 | p(1:n-k+1,k+1) = diff(p(1:n-k+2,k)); 14 | end 15 | 16 | % 计算 4 次 Newton 前插公式 17 | q = p(1,:); 18 | x = 0.048; t = (x-X(1))/h; 19 | y = q(1); z = 1; 20 | for k = 1 : 4 % 这里是 4,不是 n(=5) 21 | z = z*(t-k+1)/k; 22 | y = y + z*q(k+1); 23 | end 24 | fprintf('四次Newton前插公式的计算结果为: cos(%.3f)=%.5f\n',x,y); 25 | -------------------------------------------------------------------------------- /第四章 数值积分/gaussquad.m: -------------------------------------------------------------------------------- 1 | function q=gaussquad(fun,a,b,n,m,type) 2 | % GAUSSQUAD 一般区间[a,b]上的Gauss积分 3 | if nargin<6 4 | type='P'; % 默认Gauss公式,type可以为['P','T','P1'] 5 | end 6 | if nargin<5 || isempty(m) 7 | m=4; % 默认Gauss点数 8 | end 9 | if nargin<4 || isempty(n) 10 | n=10; % 默认区间等分数 11 | end 12 | if nargin<2; 13 | a=-1; b=1; % 默认积分区间 14 | end 15 | [x0,A]=quadcoef(m,type); % 求Gauss点及对应的求积系数 16 | h=(b-a)/n; % 每个小区间的长度 17 | q=0; % 区间[-1,1]上的积分初始值 18 | for k=1:n 19 | q=q+A.'*fun(h/2*x0+a+(k-1/2)*h); % 区间[-1,1]上的积分累加 20 | end 21 | q=h/2*q; % 变换区间为[a,b]上的积分值 22 | -------------------------------------------------------------------------------- /第二章 插值方法/application_2_2.m: -------------------------------------------------------------------------------- 1 | % 股票预测问题 by 曲线拟合 2 | %% 历史数据处理 3 | clear;clc; 4 | x = [2,3,4,5,8,9,10,11,12,15,16,17,18,19,22,23,24,25,26,29,30]; % 时间 5 | y = [7.74,7.84,7.82,7.78,7.91, 7.97,7.9,7.76,7.9,8.04,8.06, 8.11,8.08,8.13,8.03,8.01,8.06,8.0,8.3,8.41,8.28]; % 当天收盘价 6 | 7 | p=polyfit(x,y,3); % 多项式拟合,返回次数为 3 的多项式 p(x) 的系数,该阶数是 y 中数据的最佳拟合(在最小二乘方式中)。p 中的系数按降幂排列,p 的长度为 n+1 8 | plot(x,y,'*',x,polyval(p,x)); 9 | 10 | %% 开始预测 11 | x1=[31,32,33]; % 待预测时间 12 | xi=[x,x1]; 13 | y1=[8.27,8.17,9.54]; % 该股票后三个交易日的收盘价分别为8.27,8.17,9.54 14 | plot(x,y,'*',xi,polyval(p,xi),x1,y1,'rp'); 15 | % 结论:预测结果仅供参考 -------------------------------------------------------------------------------- /第七章 非线性方程解法/demo_7_5.m: -------------------------------------------------------------------------------- 1 | % Steffenson 加速 2 | clear; clc 3 | f = @(x) x^3-x-1; 4 | g = @(x) x^3-1; %普通迭代不收敛 5 | 6 | fprintf('True solution: x = %.8f\n',fzero(f,[1,2])) 7 | 8 | n = 6; % 设置迭代步数 9 | x = 1.5; % 迭代初始值 10 | 11 | % 不动点迭代 12 | fprintf('普通不动点迭代\n') 13 | for k = 1 : n 14 | x = g(x); 15 | fprintf('k=%d, x=%.8g\n',k,x); 16 | end 17 | 18 | % Steffenson 加速 19 | x = 1.5; % 迭代初始值 20 | fprintf('===================\n'); 21 | fprintf('Steffenson 加速迭代\n'); 22 | for k = 1 : n 23 | x1 = g(x); x2 = g(x1); 24 | x = x - (x1-x)^2/(x2-2*x1+x); 25 | fprintf('k=%d, x=%.8f\n',k,x); 26 | end -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_3.m: -------------------------------------------------------------------------------- 1 | % 变步长方法求数值积分 2 | clear; 3 | format long; 4 | f = @(x) sin(x)./x; % 采用数组运算,使得函数可以作用在向量或矩阵上 5 | a = 0; 6 | b = 1; 7 | tol = 1e-7; 8 | i = 0; 9 | 10 | h = b - a; 11 | T1 = (h / 2) * (1 + f(b)); 12 | T2 = 0; 13 | flag = true; 14 | while (flag) 15 | fprintf('T%d= %.10f\n', 2^i, T1); 16 | S = 0; 17 | x = a + h / 2; 18 | while (x < b) 19 | S = S + f(x); 20 | x = x + h; 21 | end 22 | T2 = T1 / 2 + h * S / 2; 23 | h = h / 2; 24 | flag = abs(T2 - T1) >= tol; 25 | T1 = T2; 26 | i = i +1; 27 | end 28 | fprintf('变步长方法计算结果 T= %.8f\n',T2); 29 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_3.m: -------------------------------------------------------------------------------- 1 | % Newton 插值 2 | clear; 3 | 4 | X = [0.5, 0.6, 0.4, 0.7]; % 插值节点 5 | Y = [ -0.6931, -0.5108, -0.9163, -0.3567]; % 函数值 6 | [p,q] = d_d(X,Y); % 计算差商, q 为差商表对角线 7 | 8 | x = 0.54; % 需要插值的点 9 | % 线性插值:取插值节点 0.5, 0.6 10 | y1 = q(1) + q(2)*(x-0.5); 11 | fprintf('线性插值的结果: %.4f\n',y1); 12 | 13 | % 二次插值:取插值节点 0.5, 0.6, 0.4 14 | y2 = q(1) + q(2)*(x-0.5) + q(3)*(x-0.5)*(x-0.6); 15 | fprintf('二次插值的结果: %.4f\n',y2); 16 | 17 | % 三次插值:取插值节点 0.5, 0.6, 0.4, 0.7 18 | y2 = q(1) + q(2)*(x-0.5) + q(3)*(x-0.5)*(x-0.6) + q(4)*(x-0.5)*(x-0.6)*(x-0.4); 19 | fprintf('三次插值的结果: %.4f\n',y2); 20 | 21 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/my_ge.m: -------------------------------------------------------------------------------- 1 | % 高斯消去法 Gaussian_Elimination 2 | function [x] = my_ge(A, b) 3 | 4 | [m,n]=size(A); 5 | if (m~=n) 6 | fprintf('\n Error: A 不是方阵!\n'); return; 7 | end 8 | 9 | m = zeros(n); 10 | %消元过程 11 | for k = 1:n-1 12 | for i = k+1:n 13 | m(i,k) = A(i,k)/A(k,k); 14 | A(i,:) = A(i,:) - m(i,k) * A(k,:); 15 | b(i) = b(i) - m(i,k) * b(k); 16 | end 17 | end 18 | %回代过程 19 | x(n) = b(n)/A(n,n); 20 | for k = n-1 : -1 : 1 21 | summary = 0; 22 | for j = k+1 : n 23 | summary = summary + A(k,j) * x(j); 24 | end 25 | x(k) = (b(k) - summary) / A(k,k); 26 | end 27 | -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/example_6_2_a.m: -------------------------------------------------------------------------------- 1 | % Gauss-Seidel 迭代法(矩阵形式)求解方程组 2 | clear; 3 | % 输入值 4 | A = [10, -1, -2; -1, 10, -2; -1, -1, 5]; 5 | b = [7.2; 8.3; 4.2]; 6 | tol = 1e-5; 7 | N = 100; 8 | x = [0; 0; 0]; 9 | 10 | D = diag(diag(A)); % A 的对角线部分 11 | L = D - tril(A); % -L 为 A 的严格下三角部分 12 | U = D - triu(A); % -U 为 A 的严格上三角部分 13 | 14 | for k = 0 : N 15 | y = (D-L) \ ( U*x + b ); % G-S公式(矩阵形式) 16 | if (max(abs(x - y)) < tol) 17 | fprintf('迭代次数: %d\n', k); 18 | fprintf('方程组的根: %10.8f\n', y); 19 | break; 20 | end 21 | x = y; 22 | end 23 | if k == N 24 | fprintf('迭代方法失败\n'); 25 | end -------------------------------------------------------------------------------- /第四章 数值积分/application_4_1.m: -------------------------------------------------------------------------------- 1 | % 复合公式求河流水流量 2 | clear; 3 | format long; 4 | a = 0; 5 | b = 700; 6 | h = 50; 7 | n = (b - a) / h; 8 | v = 0.5; % 流速 m/s 9 | 10 | X = a : h : b; 11 | Y = [4.2, 5.9, 5.8, 5.2, 4.5, 5.7, 5, 5.5, 4.8, 5.9, 4.1, 5.1, 4.6, 5.7, 4.7]; 12 | 13 | % 复合梯形公式 14 | Tn = Y(1) + 2*sum(Y(2:n)) + Y(n+1); 15 | Tn = Tn*h/2; 16 | fprintf('复合梯形公式计算的河流横截面积近似值为: %f平方米\n', Tn); 17 | fprintf('河流水流量为:%f立方米\n',Tn * v); 18 | 19 | % 复合 Simpson 公式 20 | Sn = Y(1) + Y(n+1) + 4*sum(Y(2:2:n)) + 2*sum(Y(3:2:n-1)); 21 | Sn = Sn*h/3; 22 | fprintf('复合Simpson公式计算的河流横截面积近似值为: %f平方米\n', Sn); 23 | fprintf('河流水流量为:%f立方米\n',Sn * v); 24 | -------------------------------------------------------------------------------- /第四章 数值积分/lagrange_interp.m: -------------------------------------------------------------------------------- 1 | function varargout=lagrange_interp(xdata,ydata,xi) 2 | % LAGRANGE_INTERP Lagrange插值 3 | n=length(xdata); % 求向量xdata的长度 4 | if length(unique(xdata)) abs(f(x0)) 14 | lamda = lamda / 2; % 下山因子减半 15 | fprintf('下山因子减半后的值: %d\n', lamda); 16 | x1 = x0 - lamda * f(x0) / df(x0); 17 | end 18 | fprintf('本次迭代f(x)的值: %d\n', abs(f(x1))); 19 | if abs(x1 - x0) < tol 20 | fprintf('迭代次数: %d\n', k); 21 | fprintf('方程的正根: %10.8f\n', x1); 22 | break; 23 | end 24 | x0 = x1; 25 | end 26 | if k == N 27 | fprintf('迭代方法失败\n'); 28 | end -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_1.m: -------------------------------------------------------------------------------- 1 | % lnx 插值 2 | clear; clc; 3 | X = 0.4 : 0.1 : 0.8; 4 | Y = [-0.9163, -0.6931, -0.5108, -0.3567, -0.2231]; 5 | x = 0.54; % 插值点 6 | 7 | % 线性插值 8 | x0 = X(2); y0 = Y(2); 9 | x1 = X(3); y1 = Y(3); 10 | y = y0*(x-x1)/(x0-x1) + y1*(x-x0)/(x1-x0); 11 | fprintf('线性插值的结果为:%.6f\n',y) 12 | 13 | % 抛物线插值 14 | x0 = X(2); y0 = Y(2); 15 | x1 = X(3); y1 = Y(3); 16 | x2 = X(1); y2 = Y(1); 17 | y = y0*(x-x1)*(x-x2)/((x0-x1)*(x0-x2)) + ... 18 | y1*(x-x0)*(x-x2)/((x1-x0)*(x1-x2)) + ... 19 | y2*(x-x0)*(x-x1)/((x2-x0)*(x2-x1)); 20 | fprintf('抛物线插值的结果为:%.6f\n',y) 21 | 22 | % n 次插值 23 | n = length(X) - 1; 24 | y = 0; 25 | for k = 0 : n 26 | y = y + Y(k+1)*prod(x-X([1:k,k+2:end]))/prod(X(k+1)-X([1:k,k+2:end])); 27 | end 28 | fprintf('%d次插值的结果为:%.6f\n',n, y) 29 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_14.m: -------------------------------------------------------------------------------- 1 | % 分段线性插值 点击定位插值点 2 | % 按return键结束程序 3 | clear;clc; 4 | xl = -3; xr = 3; yb= -3; yt = 3; % 可视区域 5 | plot([xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 6 | grid on; 7 | xlist = []; ylist = []; % 存储用户选择插值节点的横纵坐标 8 | k = 0; 9 | while(0 == 0) 10 | [xnew, ynew] = ginput(1); % 用户点击可视区域选择插值节点 11 | if length(xnew) < 1 12 | break 13 | end 14 | k = k+1; 15 | xlist(k) = xnew; 16 | ylist(k) = ynew; 17 | if k == 1 18 | continue; 19 | end 20 | x = xlist(1) : 0.01 : xr; % 待插值点,绘制曲线的横坐标 21 | y = interp1(xlist,ylist,x); % 根据插值函数求出的近似值 22 | 23 | plot(xlist, ylist, 'o', x, y, [xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 24 | title('分段线性插值演示'); 25 | axis([xl xr yb yt]); grid on; 26 | end 27 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_13.m: -------------------------------------------------------------------------------- 1 | % Runge 函数的Lagrange插值与三次样条插值比较 2 | clear; clc; 3 | 4 | f = @(x) 1./(1+x.^2); 5 | a = -5; b = 5; 6 | n = 10; % 10等分 7 | X = [ a : (b-a)/n : b ]; % 插值节点 8 | Y = f(X); 9 | 10 | % 用10次多项式插值 11 | x = -5 : 0.1 : 5; % 需要插值的点, 绘图用 12 | y1 = zeros(1,length(x)); 13 | for i = 1 : length(x) 14 | for k = 0 : n 15 | y1(i) = y1(i) + Y(k+1)*prod(x(i)-X([1:k,k+2:end]))/prod(X(k+1)-X([1:k,k+2:end])); 16 | end 17 | end 18 | 19 | % 三次样条插值 20 | df = @(x) -2*x/(x*x+1)^2; % 一阶导数 21 | df0 = df(-5); dfn = df(5); 22 | y2 = spline(X,[df0; Y(:); dfn], x); 23 | 24 | % 绘图 25 | plot(x,f(x),'r-', x,y1,'b-',x,y2,'k-','LineWidth',2); 26 | axis([-5,5,-1,2]); 27 | title('10次插值','FontSize',20); 28 | legend('f(x)','Lagrange','spline') 29 | hold on 30 | plot(X,Y,'or','MarkerSize',12,'LineWidth',2) 31 | hold off 32 | -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/example_6_3.m: -------------------------------------------------------------------------------- 1 | % 超松弛法(分量形式) 求解方程组 2 | clear; 3 | % 输入值 4 | A = [10, -1, -2; -1, 10, -2; -1, -1, 5]; 5 | b = [7.2; 8.3; 4.2]; 6 | tol = 1e-5; 7 | N = 100; % 最大迭代次数 8 | omega = 1.74; % 松弛因子,取值区间(0, 2) 9 | x = [0; 0; 0]; 10 | x_backup = [0; 0; 0]; 11 | y = [0; 0; 0]; 12 | % 13 | A_ = A; 14 | for i = 1 : length(A) 15 | A_(i,i) = 0; 16 | end 17 | 18 | for k = 0 : N 19 | for j = 1 : 3 20 | y(j) = (b(j) - A_(j,:) * x) / A(j,j); 21 | y(j) = (1 - omega) * x(j) + omega * y(j); 22 | x_backup(j) = x(j); % 备份“老值” 23 | x(j) = y(j); % “新值” 替换 “老值” 24 | end 25 | if (max(abs(x_backup - y)) < tol) 26 | fprintf('迭代次数: %d\n', k); 27 | fprintf('方程组的根: %10.8f\n', y); 28 | break; 29 | end 30 | end 31 | if k == N 32 | fprintf('迭代方法失败\n'); 33 | end -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_8.m: -------------------------------------------------------------------------------- 1 | % interp1 举例 2 | clear; clc; 3 | 4 | xi=0:pi/5:2*pi; % 将插值区间分成若干等距小区间 5 | yi=sin(xi); % 插值节点处的函数值 6 | 7 | xh=0:pi/20:2*pi; % 需要插值的点 8 | 9 | % 分段线性插值 10 | subplot(2,2,1) 11 | yh=interp1(xi,yi,xh); % 根据插值函数求出的近似值 12 | plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5); 13 | title('分段线性插值','FontSize',18) 14 | 15 | % 分段零次插值 16 | subplot(2,2,2) 17 | yh=interp1(xi,yi,xh,'nearst'); % 用邻近的值近似 18 | plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5); 19 | title('分段零次插值','FontSize',18) 20 | 21 | % 分段三次 Hermite 22 | subplot(2,2,3) 23 | yh=interp1(xi,yi,xh,'pchip'); 24 | plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5); 25 | title('分段三次Hermite插值','FontSize',18) 26 | 27 | % 分段三次样条插值 28 | subplot(2,2,4) 29 | yh=interp1(xi,yi,xh,'spline'); 30 | plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5); 31 | title('分段三次样条插值','FontSize',18) 32 | 33 | -------------------------------------------------------------------------------- /第二章 插值方法/bezier.m: -------------------------------------------------------------------------------- 1 | % Bezier样条 点击选择起止点和控制点 2 | plot([-1 1], [0 0], 'k', [0 0], [-1 1], 'k'); hold on 3 | t = 0 : 0.02 : 1; 4 | [x, y] = ginput(1); 5 | while (0 == 0) 6 | [xnew, ynew] = ginput(3); 7 | if length(xnew) < 3 8 | break 9 | end 10 | x = [x; xnew]; 11 | y = [y; ynew]; 12 | plot([x(1) x(2)], [y(1) y(2)], 'r:', x(2), y(2), 'rs') 13 | plot([x(3) x(4)], [y(3) y(4)], 'r:', x(3), y(3), 'rs') 14 | plot(x(1), y(1), 'bo', x(4), y(4), 'bo'); 15 | bx = 3 * (x(2) - x(1)); by = 3 * (y(2) - y(1)); 16 | cx = 3 * (x(3) - x(2)) - bx; cy = 3 * (y(3) -y(2)) -by; 17 | dx = x(4) - x(1) -bx - cx; dy = y(4) - y(1) - by -cy; 18 | xp = x(1) + t .* (bx + t .* (cx + t * dx)); 19 | yp = y(1) + t .* (by + t .* (cy + t * dy)); 20 | plot(xp, yp) 21 | x = x(4); y = y(4); 22 | end 23 | hold off -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_5.m: -------------------------------------------------------------------------------- 1 | % 梯形公式的加速--外推技巧 2 | clear; clc; 3 | f = @(x) sqrt(x.^3); 4 | a = 0; 5 | b = 1; 6 | tol = 1e-10; 7 | maxit = 100; % 最大迭代步数 8 | 9 | T(1,1) = (b-a)/2 * (f(a) + f(b)); 10 | fprintf(' T(1,1)=%.8f \n',T(1,1)); 11 | k = 1; err = 1.0; 12 | for k = 1 : maxit 13 | h = (b-a)/(2^(k-1)); 14 | T(k+1,1) = T(k,1)/2 + (h/2) * sum(f(a+0.5*h+[0:2^(k-1)-1]*h)); % 梯形递推公式 15 | fprintf(' T(%d,1)=%.8f ',k+1,T(k+1,1)); 16 | for j = 1 : k 17 | T(k+1,j+1) = (4^j * T(k+1,j) - T(k,j) )/(4^j-1); % 通过线性组合实现加速 18 | fprintf(' T(%d,%d)=%.8f ',k+1,j+1,T(k+1,j+1)); 19 | err = abs(T(k+1,j+1)-T(k+1,j)); 20 | if (err xnew 19 | xlp = xnew; 20 | end 21 | if xrp < xnew xrp = xnew; end 22 | if k == 1 23 | xlp = xnew; 24 | xrp = xnew; 25 | continue; 26 | end 27 | x = xlp : 0.01 : xrp; % 待插值点,绘制曲线的横坐标 28 | pp = spline(xlist, [0, ylist, 0]); % 第一类边界条件 29 | %pp = spline(xlist, ylist); % not a knot三次样条 30 | y = ppval(pp, x); % 计算待插值点的纵坐标 31 | plot(xlist, ylist, 'o', x, y, [xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 32 | title('三次样条插值演示'); 33 | axis([xl xr yb yt]); grid on; 34 | end 35 | -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_10.m: -------------------------------------------------------------------------------- 1 | a=2;b=5; 2 | fun=@(x)exp(-x).*sin(x)+cos(x)+2; 3 | xn=linspace(a,b); 4 | subplot(2,1,1) 5 | fplot(fun,[a-1,b+1]) 6 | hold on 7 | plot([a,b],fun([a,b]),'k.','markersize',20) 8 | plot([a,a,b,b],[0,fun([a,b]),0],'k') 9 | fill([xn,a],fun([xn,a]),[0.8,0.8,0.8],'edgecolor','none') 10 | alpha(0.5) 11 | text([a,b],fun([a,b]),{'$$(a,f(a))$$','$$(b,f(b))$$'},... 12 | 'interpreter','latex','fontsize',12,'hor','right','ver','bottom') 13 | title('梯形求积') 14 | subplot(2,1,2) 15 | fplot(fun,[a-1,b+1]) 16 | hold on 17 | [x0,A]=gausscoef(a,b,2); 18 | y=lagrange_interp(x0,fun(x0),[a,b]); 19 | plot([a,b,a,b],[fun([a,b]),y],'k.','markersize',20) 20 | plot([a,b],y,'k','markersize',20) 21 | plot([a,a],[0,fun(a)],'k') 22 | plot([b,b],[0,fun(b)],'k') 23 | plot(x0,fun(x0),'ro') 24 | fill([xn,b,a],[fun(xn),fliplr(y)],[0.8,0.8,0.8],'edgecolor','none') 25 | alpha(0.5) 26 | text([a,b,x0],fun([a,b,x0]),{'$$(a,f(a))$$','$$(b,f(b))$$',... 27 | '$$(x_0,f(x_0))$$','$$(x_1,f(x_1))$$'},... 28 | 'interpreter','latex','fontsize',12,'hor','right','ver','bottom') 29 | title('两点Gauss求积') 30 | -------------------------------------------------------------------------------- /第四章 数值积分/quadgui_simpson.m: -------------------------------------------------------------------------------- 1 | function [Qout,fcount] = quadgui_simpson(F,a,b,tol) 2 | 3 | shg 4 | clf reset 5 | set(gcf,'menubar','none','numbertitle','off','name','Quad gui') 6 | 7 | % 缺省误差限 8 | if nargin < 4 | isempty(tol) 9 | tol = 1.e-4; 10 | end 11 | 12 | % 缺省被积函数和积分区间 13 | if nargin < 3 14 | F = @humps; 15 | a = 0; 16 | b = 1; 17 | end 18 | 19 | Sn_1 = (b - a)*(F(a) + 4*F((b+a)/2) + F(b)) / 6; 20 | for n = 2:8 21 | h = (b - a) / 2^n; 22 | X = a : h : b; 23 | Y = F(X); 24 | Sn = Y(1) + Y(2^n+1) + 4*sum(Y(2:2:2^n)) + 2*sum(Y(3:2:2^n - 1)); 25 | Sn = Sn*h/3; 26 | 27 | set(gcf,'userdata',0) 28 | hold on 29 | plot(X,Y,'.','markersize',16); 30 | set(gca,'xtick',sort(X),'xticklabel',[]); 31 | title(num2str(length(X))) 32 | pause(2.5) 33 | hold off 34 | 35 | if abs(Sn - Sn_1) < tol 36 | fcount = 2^n + 1; 37 | break 38 | end 39 | Sn_1 = Sn; 40 | end 41 | Qout = Sn + (Sn - Sn_1)/15; 42 | % 结束,输出采样点数和积分结果 43 | title(sprintf('Q = %8.4f, fcount = %4.0f',Qout,fcount)) 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/my_forward_backward.m: -------------------------------------------------------------------------------- 1 | % 追赶法 分解的紧凑方式 2 | function [x] = my_forward_backward(A,f) 3 | 4 | [m,n]=size(A); 5 | if (m~=n) 6 | fprintf('\n Error: A 不是方阵!\n'); return; 7 | end 8 | 9 | a = diag(A, -1); 10 | a(2:n) = a; 11 | a(1) = 0; 12 | b = diag(A); 13 | c = diag(A, 1); 14 | 15 | % 判断是否三对角矩阵 16 | if sum(any(tril(A, -2))) > 0 | sum(any(triu(A, 2))) > 0 17 | fprintf('\n Error: A 不是三对角矩阵!\n'); x = []; return; 18 | end 19 | 20 | % 判断是否对角占优 21 | if (abs(b(1)) <= abs(c(1)) | abs(c(1)) == 0 | find(abs(b(2:n-1)) < abs(a(2:n-1)) + abs(c(2:n-1))) > 0 | abs(b(n)) <= abs(a(n))) | abs(a(n)) == 0 22 | fprintf('\n Error: A 不是对角占优矩阵!\n'); x = []; return; 23 | end 24 | 25 | alpha = zeros(n, 1); 26 | beda = zeros(n-1, 1); 27 | gamma = a; % gamma直接等于a,无需计算 28 | 29 | alpha(1) = b(1); 30 | for i = 1 : n - 1 31 | beda(i) = c(i) / alpha(i); 32 | alpha(i + 1) = b(i + 1) - a(i + 1) * beda(i); 33 | end 34 | 35 | % 求解Ly=b 和 Ux=y 36 | y(1) = f(1) / b(1); 37 | for i=2:n 38 | y(i)=(f(i) - a(i)*y(i-1)) / alpha(i); 39 | end 40 | x(n) = y(n); 41 | for i = n-1 : -1 : 1 42 | x(i)=y(i) - beda(i) * x(i+1); 43 | end 44 | 45 | 46 | % END 47 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_11.m: -------------------------------------------------------------------------------- 1 | % 样条插值举例 2 | clear; clc 3 | 4 | X = [27.7, 28, 29, 30]; 5 | Y = [4.1, 4.3, 4.1, 3.0]; 6 | df0 = 3.0; dfn = -4.0; % 第一类边界条件 7 | 8 | n = length(X) - 1; 9 | H = diff(X); % 每个插值小区间的长度 10 | mu = H(1:n-1) ./ (H(1:n-1) + H(2:n)); 11 | lambda = 1 - mu; 12 | % 计算二阶差商 13 | Y1 = diff(Y) ./ diff(X); % 一阶差商 14 | Y2 = diff(Y1) ./ ( X(3:end) - X(1:end-2) ); % 二阶差商 15 | % 计算右端项 16 | d = 6*Y2; 17 | d0 = 6/H(1) * (Y1(1) - df0); 18 | dn = 6/H(end) * (dfn - Y1(end)); 19 | % 给出系数矩阵 20 | A = 2*eye(n+1) + diag([mu(:);1],-1) +diag([1;lambda(:)],1); 21 | b = [d0; d(:); dn]; 22 | M = A\b; 23 | 24 | % 计算 s_k(x) 的系数, 两种形式 25 | p = zeros(n,4); p0 = zeros(n,4); 26 | for k = 1 : n 27 | p(k,1) = (M(k+1) - M(k))/(6*H(k)); 28 | p(k,2) = M(k)/2; 29 | p(k,3) = (Y(k+1) - Y(k))/ H(k) - H(k)/6 * (2*M(k) + M(k+1)); 30 | p(k,4) = Y(k); 31 | p0(k,1) = M(k)/(6*H(k)); 32 | p0(k,2) = M(k+1)/(6*H(k)); 33 | p0(k,3) = (Y(k) - M(k)*H(k)*H(k)/6) / H(k); 34 | p0(k,4) = (Y(k+1) - M(k+1)*H(k)*H(k)/6) / H(k); 35 | end 36 | 37 | % 调用 Matlab 的三次样条插值函数 38 | pp = spline(X, [df0;Y(:);dfn]); 39 | 40 | %输出结果 41 | fprintf('按形式一输出: \n'); disp(p0); 42 | fprintf('按形式二输出: \n'); disp(p); 43 | fprintf('spline的结果(形式二): \n'); disp(pp.coefs); 44 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_0.m: -------------------------------------------------------------------------------- 1 | % 多项式插值 点击定位数据点 2 | % 按return键结束程序 3 | clear;clc; 4 | xl = -3; xr = 3; yb= -3; yt = 3; % 可视区域 5 | plot([xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 6 | grid on; 7 | xlist = []; ylist = []; % 存储用户选择插值节点的横纵坐标 8 | k = 0; 9 | while(0 == 0) 10 | [xnew, ynew] = ginput(1); % 用户点击可视区域选择插值节点 11 | if length(xnew) < 1 12 | break 13 | end 14 | k = k+1; 15 | xlist(k) = xnew; 16 | ylist(k) = ynew; 17 | [m,c] = d_d(xlist, ylist); % 根据插值节点计算差商表,返回对角线元素 18 | 19 | poly_exp = 'y = '; omiga_exp = ''; 20 | for index = 1 : length(c) 21 | if c(index) >= 0 22 | coef_str = ['+', num2str(c(index))]; 23 | else 24 | coef_str = num2str(c(index)); 25 | end 26 | poly_exp = [poly_exp, coef_str,omiga_exp]; 27 | if -xlist(index) >= 0 28 | omiga_sub = ['+', num2str(-xlist(index))]; 29 | else 30 | omiga_sub = num2str(-xlist(index)); 31 | end 32 | omiga_exp = [omiga_exp, '(x', omiga_sub,')']; 33 | end 34 | 35 | 36 | x = xl : 0.01 : xr; % 待插值点,绘制曲线的横坐标 37 | y = nest(c, x, xlist); % 计算待插值点的纵坐标 38 | plot(xlist, ylist, 'o', x, y, [xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 39 | title('多项式插值演示'); 40 | text(xl, yt - 0.5, poly_exp); 41 | axis([xl xr yb yt]); grid on; 42 | end 43 | -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_7.m: -------------------------------------------------------------------------------- 1 | % 复合求积基本思想 2 | clear; clc; 3 | % 被积函数 F 4 | F = @(x) (+1.0146-0.88571.*(x-0.20046)+4.4375.*(x-0.20046).*(x-0.75346)-2.8282.*(x-0.20046).*(x-0.75346).*(x-1.1129)+2.8895.*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433)+0.62844*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433).*(x-1.9562)); 5 | 6 | a = 1.0; % 积分区间下限 7 | b = 2.5; % 积分区间上限 8 | hi = 0.05; % 绘图步长 9 | xi = a : hi : b; 10 | yi = ones(size(xi)) .* F(xi); 11 | N = 4; % 分段数 12 | xs = linspace(a, b, N + 1); % 样本点 x 坐标,分段点 13 | ys = F(xs); % 样本点 y 坐标 14 | xl = 0.5; xr = 3; yb= 0; yt = 5; % 坐标系可视区域 15 | 16 | % 复合梯形法的几何意义 17 | subplot(1,2,1); 18 | plot(xi,yi, xs, ys, 'rp-'); 19 | hold on; 20 | stem(xi,yi,'k'); 21 | title('复合梯形法的几何意义'); 22 | axis([xl xr yb yt]); grid on; 23 | 24 | % 复合Simpson法的几何意义 25 | subplot(1,2,2); 26 | xm = xs(1 : end-1) + (b - a) / (2 * N); 27 | ym = F(xm); 28 | plot(xi,yi, xs, ys, 'rp', xm, ym, 'bp'); 29 | hold on; 30 | for i = 1 : N 31 | xna = xs(i); yna = ys(i); 32 | xnb = xs(i+1); ynb = ys(i+1); 33 | xnm = xm(i); ynm = ym(i); 34 | xni = linspace(xna, xnb, 100); 35 | yni = yna*(xni-xnm).*(xni-xnb)./((xna-xnm).*(xna-xnb)) + ynm * (xni - xna) .* (xni - xnb) ./ ((xnm - xna) .* (xnm - xnb)) + ynb * (xni - xna).*(xni-xnm) ./ ((xnb-xna).*(xnb-xnm)); 36 | plot(xni, yni); 37 | hold on; 38 | end 39 | stem(xi,yi,'k'); 40 | title('复合Simpson法的几何意义'); 41 | axis([xl xr yb yt]); grid on; 42 | 43 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/my_doolittle.m: -------------------------------------------------------------------------------- 1 | % 列主元 Doolittle 分解的紧凑方式 2 | function [L, U, x] = my_doolittle(A, b) 3 | 4 | [m,n]=size(A); 5 | if (m~=n) 6 | fprintf('\n Error: A 不是方阵!\n'); return; 7 | end 8 | 9 | L = eye(n); 10 | U = zeros(n); 11 | 12 | A_ = A; 13 | 14 | Ip=1:n;%它的第k个元素M(k)记录第k个主元素所在的行号 15 | 16 | for k = 1:n 17 | % 第一步 做分解PA=LU,P是置换矩阵,即实现选主元素 18 | [v, h] = max(abs(A_(k:n,k))); 19 | h = k + h -1; 20 | Ip(k) = h ; 21 | temp = A_(k,:); 22 | A_(k,:) = A_(h,:); 23 | A_(h,:) = temp; 24 | 25 | A_(k,k) = A_(k,k)-sum(A_(k,1:k-1)'.*A_(1:k-1,k)); 26 | if (A_(k,k) == 0) 27 | fprintf('\n Error: 第 %d 个主元=0 !\n',k); return; 28 | end 29 | for j = k+1:n 30 | A_(k,j) = A_(k,j) - sum(A_(k,1:k-1)'.*A_(1:k-1,j)); 31 | A_(j,k) = (A_(j,k) - sum( A_(j,1:k-1)'.*A_(1:k-1,k) ))/A_(k,k); 32 | 33 | end 34 | 35 | end 36 | L = tril(A_,-1) + eye(n); 37 | U = triu(A_); 38 | 39 | for i = 1:n 40 | t = Ip(i); 41 | if t ~= i 42 | temp = b(i); 43 | b(i) = b(t); 44 | b(t) = temp; 45 | end 46 | end 47 | 48 | y = 1:n; 49 | y(1) = b(1); 50 | for i=2:n 51 | summary = 0; 52 | for t=1:i-1 53 | summary = summary + L(i,t) * y(t); 54 | end 55 | y(i)=b(i) - summary; 56 | end 57 | x(n) = y(n)/U(n,n); 58 | for i = n-1 : -1 : 1 59 | summary = 0; 60 | for t=i+1:n 61 | summary = summary + U(i,t) * x(t); 62 | end 63 | x(i)=(y(i) - summary)/U(i,i); 64 | end 65 | 66 | %END -------------------------------------------------------------------------------- /第六章 线性方程组迭代解法/demo_6_3.m: -------------------------------------------------------------------------------- 1 | % Jacobi, G-S 和 SOR 的演示 2 | 3 | % 以第五章 习题 9 为例(第 177 页),即三对角线性方程组 4 | clear all; 5 | 6 | n = 128; 7 | A = 2*eye(n) - diag(ones(n-1,1),1) - diag(ones(n-1,1),-1); 8 | b = eye(n,1); 9 | 10 | D = diag(diag(A)); % A 的对角线部分 11 | L = D - tril(A); % -L 为 A 的严格下三角部分 12 | U = D - triu(A); % -U 为 A 的严格上三角部分 13 | 14 | x0 = zeros(n,1); % 迭代初始值 15 | itermax = 100; % 迭代步数 16 | 17 | % Jacobi 方法 18 | x = x0; 19 | relerr_J = zeros(n+1,1); % 记录相对残量 20 | relerr_J(1) = 1; 21 | for k = 1 : itermax 22 | x = D \ ( (L+U)*x + b ); 23 | relerr_J(k+1) = norm(b - A*x) / norm(b); 24 | end 25 | 26 | % G-S 方法 27 | x = x0; 28 | relerr_GS = zeros(n+1,1); % 记录相对残量 29 | relerr_GS(1) = 1; 30 | for k = 1 : itermax 31 | x = (D-L) \ ( U*x + b ); 32 | relerr_GS(k+1) = norm(b - A*x) / norm(b); 33 | end 34 | 35 | % SOR 方法 36 | omega = 1.5; % 参数 37 | x = x0; 38 | relerr_SOR = zeros(n+1,1); % 记录相对残量 39 | relerr_SOR(1) = 1; 40 | for k = 1 : itermax 41 | x = (D-omega*L) \ ( ((1-omega)*D + omega*U)*x + omega*b ); 42 | relerr_SOR(k+1) = norm(b - A*x) / norm(b); 43 | end 44 | 45 | % plot the error 46 | step = 1; 47 | xx = 1 : step : itermax+1; 48 | 49 | plot(xx, relerr_J(xx),'-b+'); 50 | hold on 51 | plot(xx, relerr_GS(xx),'-ro'); 52 | plot(xx, relerr_SOR(xx),'-kd'); 53 | 54 | % semilogy(xx, relerr_J(xx),'-b+'); 55 | % hold on 56 | % semilogy(xx, relerr_GS(xx),'-ro'); 57 | % semilogy(xx, relerr_SOR(xx),'-kd'); 58 | 59 | legend('Jacobi', 'GS', 'SOR'); 60 | title(['n=',int2str(n)]); 61 | hold off; shg 62 | 63 | -------------------------------------------------------------------------------- /第三章 函数逼近/demo_3_0.m: -------------------------------------------------------------------------------- 1 | % 分段线性插值 点击定位插值点 2 | % 按return键结束程序 3 | clear;clc; 4 | xl = -3; xr = 3; yb= -3; yt = 3; % 可视区域 5 | plot([xl xr], [0 0], 'k', [0 0], [yb yt], 'k'); 6 | grid on; 7 | xlist = []; ylist = []; % 存储用户选择插值节点的横纵坐标 8 | k = 0; 9 | while(0 == 0) 10 | [xnew, ynew] = ginput(1); % 用户点击可视区域选择插值节点 11 | if length(xnew) < 1 12 | break 13 | end 14 | k = k+1; 15 | xlist(k) = xnew; 16 | ylist(k) = ynew; 17 | if k == 1 18 | continue; 19 | end 20 | x = xl : 0.01 : xr; % 待插值点,绘制曲线的横坐标 21 | y = interp1(xlist,ylist,x); % 根据插值函数求出的近似值 22 | 23 | [m,c] = d_d(xlist, ylist); % 根据插值节点计算差商表,返回对角线元素 24 | x_newton = xl : 0.01 : xr; % 待插值点,绘制曲线的横坐标 25 | y_newton = nest(c, x_newton, xlist); % 计算待插值点的纵坐标 26 | 27 | 28 | A = [length(xlist), sum(xlist); sum(xlist), sum(xlist .* xlist)]; % 法方程系数矩阵 29 | b = [sum(ylist); sum(xlist .* ylist)]; % 法方程常数项 30 | % pa = inv(A)*b; % 左乘逆矩阵,求解法方程组 31 | pa = A\b; 32 | 33 | pa = pa(end : -1 : 1); % 多项式系数 34 | %px = 0 : 0.01 : 10; % 画直线函数的横坐标 35 | y_fitting = polyval(pa, x); % 多项式求值 36 | 37 | %plot(xlist, ylist, 'o', x, y, [xl xr], [0 0], 'k', [0 0], [yb yt], 'k', x_newton, y_newton, x, y_fitting); 38 | plot(xlist, ylist, 'o', [xl xr], [0 0], 'k', [0 0], [yb yt], 'k', x_newton, y_newton, x, y_fitting); 39 | %plot(xlist, ylist, 'o', [xl xr], [0 0], 'k', [0 0], [yb yt], 'k', x, y_fitting); 40 | title('牛顿插值、分段线性插值、曲线拟合演示'); 41 | axis([xl xr yb yt]); grid on; 42 | end 43 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/my_lu_with_column_pivoting.m: -------------------------------------------------------------------------------- 1 | % 列主元 Doolittle 分解的紧凑方式 2 | function [L, U, x] = my_lu_with_column_pivoting(A, b) 3 | 4 | [m,n]=size(A); 5 | if (m~=n) 6 | fprintf('\n Error: A 不是方阵!\n'); return; 7 | end 8 | 9 | L = eye(n); 10 | U = zeros(n); 11 | 12 | Ip=1:n; %它的第k个元素M(k)记录第k个主元素所在的行号 13 | 14 | for k = 1:n 15 | % 做分解PA=LU,P是排列矩阵,即实现选主元素,并进行行交换 16 | [v, h] = max(abs(A(k:n,k))); 17 | h = k + h -1; 18 | Ip(k) = h ; 19 | temp = A(k,:); 20 | A(k,:) = A(h,:); 21 | A(h,:) = temp; 22 | 23 | A(k,k) = A(k,k)-sum(A(k,1:k-1)'.*A(1:k-1,k)); 24 | if (A(k,k) == 0) 25 | fprintf('\n Error: 第 %d 个主元=0 !\n',k); return; 26 | end 27 | for j = k+1:n 28 | % L和U矩阵直接存储在A矩阵中,可以节省存储空间 29 | A(k,j) = A(k,j) - sum(A(k,1:k-1)'.*A(1:k-1,j)); 30 | A(j,k) = (A(j,k) - sum( A(j,1:k-1)'.*A(1:k-1,k) ))/A(k,k); 31 | end 32 | 33 | end 34 | L = tril(A,-1) + eye(n); 35 | U = triu(A); 36 | 37 | for i = 1:n 38 | t = Ip(i); 39 | if t ~= i 40 | temp = b(i); 41 | b(i) = b(t); 42 | b(t) = temp; 43 | end 44 | end 45 | 46 | y = 1:n; 47 | y(1) = b(1); 48 | for i=2:n 49 | summary = 0; 50 | for t=1:i-1 51 | summary = summary + L(i,t) * y(t); 52 | end 53 | y(i)=b(i) - summary; 54 | % 紧凑方式 55 | % t = (1 : i-1)'; 56 | % y(i) = b(i) - sum(L(i,t) .* y(t)); 57 | end 58 | x(n) = y(n)/U(n,n); 59 | for i = n-1 : -1 : 1 60 | summary = 0; 61 | for t=i+1:n 62 | summary = summary + U(i,t) * x(t); 63 | end 64 | x(i)=(y(i) - summary)/U(i,i); 65 | end 66 | 67 | %END -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_6.m: -------------------------------------------------------------------------------- 1 | % 线性插值和三次Hermite插值(单段) 2 | clear; clc; close all; 3 | f = @(x) 1./(1+x.^2); % 函数表达式 4 | df = @(x) -(2*x)./(x.^2 + 1).^2; % 一阶导数, 用于Hermite插值 5 | a = -1; b = 2; % 插值区间 6 | n = 1; % 区间等分数 7 | h = (b-a)/n; 8 | xi = a : h : b; % 插值节点 9 | fi = f(xi); % 插值节点上的函数值 10 | dfi = df(xi); % 一阶导数值 11 | 12 | x = a : (b-a)/500 : b; % 需要插值的点 13 | 14 | % 定义线性插值函数 15 | L1 = @(x,x0,x1,y0,y1) y0*(x-x1)/(x0-x1) + y1*(x-x0)/(x1-x0); 16 | 17 | % 定义两点三次Hermite插值函数 18 | H3 = @(x,x0,x1,y0,y1,df0,df1) ... 19 | (y0*(1+2*(x-x0)/(x1-x0))+df0*(x-x0))*((x-x1)/(x0-x1))^2 + ... 20 | (y1*(1+2*(x-x1)/(x0-x1))+df1*(x-x1))*((x-x0)/(x1-x0))^2; 21 | 22 | % 线性插值 23 | N = length(x); 24 | y1 = zeros(1,N); % 线性插值 25 | y2 = zeros(1,N); % 三次Hermite插值 26 | for j = 1 : N 27 | % idx = find(xi>=x(j)); % 寻找 x(j) 所在的小区间 [x_k,x_{k+1}] 28 | % k = idx(1)-1; 29 | % if k==0 30 | % k = k + 1; 31 | % end 32 | for k=1:n+1 % 寻找 x(j) 所在的小区间 [x_k,x_{k+1}] 33 | if xi(k) >= x(j) 34 | break; % 找到第一个不小于 x(j) 的插值节点 35 | end 36 | end 37 | if k>1 38 | k=k-1; 39 | end 40 | % fprintf('x(j)=%.2f, k=%d, 插值小区间: [%.2f,%.2f]\n', ... 41 | % x(j), k, xi(k),xi(k+1)) 42 | y1(j) = L1(x(j),xi(k),xi(k+1),fi(k),fi(k+1)); 43 | y2(j) = H3(x(j),xi(k),xi(k+1),fi(k),fi(k+1),dfi(k),dfi(k+1)); 44 | end 45 | 46 | % 绘图 47 | hold on; 48 | plot(x,f(x),'r-', 'LineWidth',2); % f(x) 图像 49 | plot(x,y1,'b-', 'LineWidth',2,'markersize',5); % 分段线性插值图像 50 | plot(x,y2,'k-', 'LineWidth',2,'markersize',10); % 分段三次Hermite插值图像 51 | legend('f(x)','L1(x)','H3(x)'); 52 | titstr=['n=',int2str(n)]; title(titstr,'fontsize',14); 53 | %axis([-5,5,-1,2]); 54 | 55 | plot(xi,fi,'ok','markersize',10,'LineWidth',1.5); % 绘制插值节点 56 | hold off 57 | -------------------------------------------------------------------------------- /第二章 插值方法/demo_2_7.m: -------------------------------------------------------------------------------- 1 | % 分段线性插值和分段三次Hermite插值 2 | clear; clc; close all; 3 | f = @(x) 1./(1+x.^2); % 函数表达式 4 | df = @(x) -(2*x)./(x.^2 + 1).^2; % 一阶导数, 用于Hermite插值 5 | a = -5; b = 5; % 插值区间 6 | n = 4; % 区间等分数 7 | h = (b-a)/n; 8 | xi = a : h : b; % 插值节点 9 | fi = f(xi); % 插值节点上的函数值 10 | dfi = df(xi); % 一阶导数值 11 | 12 | x = a : (b-a)/500 : b; % 需要插值的点 13 | 14 | % 定义线性插值函数 15 | L1 = @(x,x0,x1,y0,y1) y0*(x-x1)/(x0-x1) + y1*(x-x0)/(x1-x0); 16 | 17 | % 定义两点三次Hermite插值函数 18 | H3 = @(x,x0,x1,y0,y1,df0,df1) ... 19 | (y0*(1+2*(x-x0)/(x1-x0))+df0*(x-x0))*((x-x1)/(x0-x1))^2 + ... 20 | (y1*(1+2*(x-x1)/(x0-x1))+df1*(x-x1))*((x-x0)/(x1-x0))^2; 21 | 22 | % 分段线性插值 23 | N = length(x); 24 | y1 = zeros(1,N); % 分段线性插值 25 | y2 = zeros(1,N); % 分段三次Hermite插值 26 | for j = 1 : N 27 | % idx = find(xi>=x(j)); % 寻找 x(j) 所在的小区间 [x_k,x_{k+1}] 28 | % k = idx(1)-1; 29 | % if k==0 30 | % k = k + 1; 31 | % end 32 | for k=1:n+1 % 寻找 x(j) 所在的小区间 [x_k,x_{k+1}] 33 | if xi(k) >= x(j) 34 | break; % 找到第一个不小于 x(j) 的插值节点 35 | end 36 | end 37 | if k>1 38 | k=k-1; 39 | end 40 | % fprintf('x(j)=%.2f, k=%d, 插值小区间: [%.2f,%.2f]\n', ... 41 | % x(j), k, xi(k),xi(k+1)) 42 | y1(j) = L1(x(j),xi(k),xi(k+1),fi(k),fi(k+1)); 43 | y2(j) = H3(x(j),xi(k),xi(k+1),fi(k),fi(k+1),dfi(k),dfi(k+1)); 44 | end 45 | 46 | % 绘图 47 | hold on; 48 | plot(x,f(x),'r-', 'LineWidth',2); % f(x) 图像 49 | plot(x,y1,'b-', 'LineWidth',2,'markersize',5); % 分段线性插值图像 50 | plot(x,y2,'k-', 'LineWidth',2,'markersize',10); % 分段三次Hermite插值图像 51 | legend('f(x)','L1(x)','H3(x)'); 52 | titstr=['n=',int2str(n)]; title(titstr,'fontsize',14); 53 | axis([-5,5,-1,2]); 54 | 55 | plot(xi,fi,'ok','markersize',10,'LineWidth',1.5); % 绘制插值节点 56 | hold off 57 | -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_0.m: -------------------------------------------------------------------------------- 1 | % 基本思想 几个简单公式 2 | clear; clc; 3 | % 被积函数 F 4 | F = @(x) (+1.0146-0.88571.*(x-0.20046)+4.4375.*(x-0.20046).*(x-0.75346)-2.8282.*(x-0.20046).*(x-0.75346).*(x-1.1129)+2.8895.*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433)+0.62844*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433).*(x-1.9562)); 5 | %F = @(x) 1; 6 | %F = @(x) x; 7 | %F = @(x) x.^2; 8 | %F = @(x) x.^3; 9 | a = 1.0; % 积分区间下限 10 | b = 2.5; % 积分区间上限 11 | h = 0.05; % 绘图步长 12 | xi = a : h : b; 13 | yi = ones(size(xi)) .* F(xi); 14 | xl = 0.5; xr = 3; yb= 0; yt = 5; % 坐标系可视区域 15 | 16 | % 定积分的几何意义 17 | subplot(2,3,1) 18 | plot(xi,yi); 19 | hold on; 20 | stem(xi,yi,'k'); 21 | title('定积分的几何意义'); 22 | axis([xl xr yb yt]); grid on; 23 | 24 | % 左矩形公式 25 | subplot(2,3,2) 26 | plot(xi,yi); 27 | hold on; 28 | y = yi(1) * ones(size(xi)); % 左点函数值 29 | stem(xi,y,'k'); 30 | title('左点法'); 31 | axis([xl xr yb yt]); grid on; 32 | 33 | % 右矩形公式 34 | subplot(2,3,3) 35 | plot(xi,yi); 36 | hold on; 37 | y = yi(end) * ones(size(xi)); % 右点函数值 38 | stem(xi,y,'k'); 39 | title('右点法'); 40 | axis([xl xr yb yt]); grid on; 41 | 42 | % 中矩形公式 43 | subplot(2,3,4) 44 | plot(xi,yi); 45 | hold on; 46 | y = F((a+b)/2) * ones(size(xi)); % 中点函数值 47 | stem(xi,y,'k'); 48 | title('中点法'); 49 | axis([xl xr yb yt]); grid on; 50 | 51 | % 梯形公式 52 | subplot(2,3,5) 53 | y = yi(1)*(xi-b)/(a-b) + yi(end)*(xi-a)/(b-a); % 线性插值 54 | plot(xi,yi); 55 | hold on; 56 | stem(xi,y,'k'); 57 | title('梯形公式'); 58 | axis([xl xr yb yt]); grid on; 59 | 60 | % 抛物线公式 61 | subplot(2,3,6) 62 | xz=(a+b)/2; yz = F(xz); % 被积函数的中点 63 | y = yi(1)*(xi-b).*(xi-xz)./((a-b)*(a-xz)) + yz*(xi-a).*(xi-b)./((xz-a).*(xz-b)) + yi(end)*(xi-a).*(xi-xz)./((b-a)*(b-xz)); % 抛物线插值 64 | plot(xi,yi); 65 | hold on; 66 | stem(xi,y,'k'); 67 | title('抛物线公式'); 68 | axis([xl xr yb yt]); grid on; 69 | -------------------------------------------------------------------------------- /第四章 数值积分/application_4_2.m: -------------------------------------------------------------------------------- 1 | % Romberg算法求峡谷索桥长度 2 | clear; 3 | format long; 4 | f = @(x) cosh(x/5); % 索桥的曲线函数是双曲余弦 5 | a = 0; 6 | b = 3; 7 | tol = 1e-6; 8 | 9 | h = b - a; 10 | T1 = (h / 2) * (1 + f(b)); 11 | k = 1; 12 | T2 = 0; 13 | fprintf('T%d= %f\n', 2^0, T1); 14 | flag = true; 15 | while (flag) 16 | S = 0; 17 | x = a + h / 2; 18 | while (x < b) 19 | S = S + f(x); 20 | x = x + h; 21 | end 22 | T2 = T1 / 2 + h * S / 2; % 计算梯形序列下一个二分结果 23 | fprintf('T%d= %f\n', 2^k, T2); 24 | S2 = T2 + (T2 - T1) / 3; % 线性组合外推至Simpson序列 25 | fprintf('S%d= %f\n', 2^(k-1), S2); 26 | if k == 1 27 | k = k + 1; 28 | h = h / 2; 29 | T1 = T2; 30 | S1 = S2; 31 | else 32 | C2 = S2 + (S2 - S1) / 15; % 线性组合外推至Cotes序列 33 | fprintf('C%d= %f\n', 2^(k-2), C2); 34 | if k == 2 35 | C1 = C2; 36 | k = k + 1; 37 | h = h / 2; 38 | T1 = T2; 39 | S1 = S2; 40 | else 41 | R2 = C2 + (C2 - C1) / 63; % 线性组合外推至Romberg序列 42 | fprintf('R%d= %f\n', 2^(k-3), R2); 43 | if k == 3 44 | R1 = R2; 45 | C1 = C2; 46 | k = k + 1; 47 | h = h / 2; 48 | T1 = T2; 49 | S1 = S2; 50 | else if abs(R2 - R1) >= tol 51 | R1 = R2; 52 | C1 = C2; 53 | k = k + 1; 54 | h = h / 2; 55 | T1 = T2; 56 | S1 = S2; 57 | else 58 | flag = false; 59 | fprintf('Romberg算法求峡谷索桥长度 计算结果:%f米\n',R2 * 2); 60 | end 61 | end 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_4.m: -------------------------------------------------------------------------------- 1 | % Romber算法求数值积分,结合p69图2-3看加工流程 2 | clear; 3 | format long; 4 | f = @(x) sin(x)./x; % 采用数组运算,使得函数可以作用在向量或矩阵上 5 | a = 0; 6 | b = 1; 7 | tol = 1e-6; 8 | 9 | h = b - a; 10 | T1 = (h / 2) * (1 + f(b)); 11 | k = 1; 12 | T2 = 0; 13 | fprintf('T%d= %f\n', 2^0, T1); 14 | flag = true; 15 | while (flag) 16 | S = 0; 17 | x = a + h / 2; 18 | while (x < b) 19 | S = S + f(x); 20 | x = x + h; 21 | end 22 | T2 = T1 / 2 + h * S / 2; % 计算梯形序列下一个二分结果 23 | fprintf('T%d= %f\n', 2^k, T2); 24 | S2 = T2 + (T2 - T1) / 3; % 线性组合外推至Simpson序列 25 | fprintf('S%d= %f\n', 2^(k-1), S2); 26 | if k == 1 27 | k = k + 1; 28 | h = h / 2; 29 | T1 = T2; 30 | S1 = S2; 31 | else 32 | C2 = S2 + (S2 - S1) / 15; % 线性组合外推至Cotes序列 33 | fprintf('C%d= %f\n', 2^(k-2), C2); 34 | if k == 2 35 | C1 = C2; 36 | k = k + 1; 37 | h = h / 2; 38 | T1 = T2; 39 | S1 = S2; 40 | else 41 | R2 = C2 + (C2 - C1) / 63; % 线性组合外推至Romberg序列 42 | fprintf('R%d= %f\n', 2^(k-3), R2); 43 | if k == 3 44 | R1 = R2; 45 | C1 = C2; 46 | k = k + 1; 47 | h = h / 2; 48 | T1 = T2; 49 | S1 = S2; 50 | else if abs(R2 - R1) >= tol 51 | R1 = R2; 52 | C1 = C2; 53 | k = k + 1; 54 | h = h / 2; 55 | T1 = T2; 56 | S1 = S2; 57 | else 58 | flag = false; 59 | fprintf('Romber算法求数值积分 计算结果:%.10f\n',R2); 60 | end 61 | end 62 | end 63 | end 64 | end -------------------------------------------------------------------------------- /第四章 数值积分/demo_4_6.m: -------------------------------------------------------------------------------- 1 | % Newton-Cotes公式求数值积分几何意义演示 2 | clear; 3 | format long; 4 | % 被积函数 F 5 | F = @(x) (+1.0146-0.88571.*(x-0.20046)+4.4375.*(x-0.20046).*(x-0.75346)-2.8282.*(x-0.20046).*(x-0.75346).*(x-1.1129)+2.8895.*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433)+0.62844*(x-0.20046).*(x-0.75346).*(x-1.1129).*(x-2.3433).*(x-1.9562)); 6 | a = 1.0; % 积分区间下限 7 | b = 2.5; % 积分区间上限 8 | N = 60; % 样本点数 9 | xi = linspace(a,b,N); 10 | yi = F(xi); 11 | xl = 0.5; xr = 3; yb= 0; yt = 5; % 坐标系可视区域 12 | 13 | % Newton-Cotes系数表 14 | Ck{1} = [1/2, 1/2]; 15 | Ck{2} = [1/6, 2/3, 1/6]; 16 | Ck{3} = [1/8, 3/8, 3/8, 1/8]; 17 | 18 | % 定积分的几何意义 19 | subplot(2,2,1) 20 | plot(xi,yi); 21 | hold on; 22 | stem(xi,yi,'k'); 23 | title('定积分几何意义'); 24 | axis([xl xr yb yt]); grid on; 25 | 26 | % n = 1 27 | subplot(2,2,2) 28 | plot(xi,yi); 29 | hold on; 30 | y = ones(size(xi)); 31 | y(1:N*Ck{1}(1)) = F(a); % 左点函数值 32 | y(N*Ck{1}(2) + 1 : end) = F(b); % 右点函数值 33 | stem(xi,y,'k'); 34 | title('n = 1'); 35 | axis([xl xr yb yt]); grid on; 36 | 37 | % n = 2 38 | subplot(2,2,3) 39 | plot(xi,yi); 40 | hold on; 41 | y = ones(size(xi)); 42 | y(1 : round(N*Ck{2}(1))) = F(a); % 左点函数值 43 | xz=(a+b)/2; yz = F(xz); % 被积函数的中点 44 | y(round(N*Ck{2}(1)) : round(N*(Ck{2}(1) + Ck{2}(2)))) = yz; % 中点函数值 45 | y(round(N*(Ck{2}(1) + Ck{2}(2))) : end) = F(b); % 右点函数值 46 | stem(xi,y,'k'); 47 | title('n = 2'); 48 | axis([xl xr yb yt]); grid on; 49 | 50 | % n = 3 51 | subplot(2,2,4) 52 | plot(xi,yi); 53 | hold on; 54 | y = ones(size(xi)); 55 | y(1:round(N*Ck{3}(1))) = F(a); % 左点函数值 56 | xz = a + (b - a) / 3; yz = F(xz); % 被积函数的1/3点 57 | y(round(N*Ck{3}(1)) : round(N*(Ck{3}(1) + Ck{3}(2)))) = yz; % 1/3点函数值 58 | xz = a + 2 * (b - a) / 3; yz = F(xz); % 被积函数的2/3点 59 | y(round(N*(Ck{3}(1) + Ck{3}(2))) : round(N*(Ck{3}(1) + 2 * Ck{3}(2)))) = yz; % 2/3点函数值 60 | y(round(N*(Ck{3}(1) + 2 * Ck{3}(2))) : end) = F(b); % 右点函数值 61 | stem(xi,y,'k'); 62 | title('n = 3'); 63 | axis([xl xr yb yt]); grid on; -------------------------------------------------------------------------------- /第四章 数值积分/quadgui_adaptive.m: -------------------------------------------------------------------------------- 1 | function [Qout,fcount] = quadgui_adaptive(F,a,b,tol,varargin) 2 | %QUADGUI Demonstrate numerical evaluation of a definite integral. 3 | % Q = QUADGUI(F,A,B) shows the steps in approximating the integral 4 | % of F(x) from A to B by adaptive extrapolated Simpson's quadrature. 5 | % 6 | % The shaded area shows the integral over the current subinterval. 7 | % The color switches to green when the desired accuracy is obtained. 8 | % 9 | % Q = QUADGUI(F,A,B,tol) uses the given tolerance instead of 1.e-4. 10 | % 11 | % The first argument, F, is a function handle or an anonymous function 12 | % that defines F(x). 13 | % Arguments beyond the first four, Q = QUADGUI(F,a,b,tol,p1,p2,...), 14 | % are passed on to the integrand, F(x,p1,p2,..). 15 | % 16 | % [Q,fcount] = QUADGUI(F,...) also counts the number of evaluations 17 | % of F(x). 18 | % 19 | % Examples: 20 | % F a b tol(optional) 21 | % humps(x) 0 1 22 | % humps(x) 0 1 1.e-6 23 | % humps(x) -1 2 24 | % sin(x) 0 pi 1.e-8 25 | % cos(x) 0 9*pi/2 1.e-6 26 | % sqrt(x) 0 1 1.e-8 27 | % -sqrt(x)*log(x) eps 1 1.e-8 28 | % 1/(3*x-1) 0 1 29 | % t^(8/3)*(1-t)^(10/3) 0 1 1.e-8 30 | % tan(sin(x))-sin(tan(x)) 0 pi 31 | % 32 | % quadgui(@(x)F,a,b) 33 | % 34 | % See also QUADTX, QUAD, QUADL, DBLQUAD. 35 | 36 | % Copyright 2014 Cleve Moler 37 | % Copyright 2014 The MathWorks, Inc. 38 | 39 | shg 40 | clf reset 41 | set(gcf,'menubar','none','numbertitle','off','name','Quad gui') 42 | 43 | % Default tolerance 44 | if nargin < 4 | isempty(tol) 45 | tol = 1.e-4; 46 | end 47 | 48 | % Default function and interval. 49 | if nargin < 3 50 | F = @humps; 51 | a = 0; 52 | b = 1; 53 | end 54 | 55 | % Initialization 56 | c = (a + b)/2; 57 | fa = F(a,varargin{:}); 58 | fc = F(c,varargin{:}); 59 | fb = F(b,varargin{:}); 60 | 61 | % Scale the plot 62 | h = b - a; 63 | x = [a c b]; 64 | y = [fa fc fb]; 65 | maxy = max(y); 66 | miny = min(y); 67 | for k = 1:63 68 | v = F(a+k*h/64,varargin{:}); 69 | maxy = real(max(maxy,v)); 70 | miny = real(min(miny,v)); 71 | end 72 | set(gcf,'userdata',0) 73 | hold on 74 | p(1) = fill(a,fa,'k'); 75 | p(2) = fill(b,fb,'k'); 76 | p(3) = plot(x,y,'.','markersize',16); 77 | hold off 78 | s = (maxy - miny)/20; 79 | axis([a b miny-s maxy+s]) 80 | q(1) = uicontrol('string','step', ... 81 | 'units','normal','pos',[.65 .02 .08 .06], ... 82 | 'callback','set(gcf,''userdata'',1)'); 83 | q(2) = uicontrol('string','auto', ... 84 | 'units','normal','pos',[.75 .02 .08 .06], ... 85 | 'callback','set(gcf,''userdata'',2)'); 86 | q(3) = uicontrol('string','quit', ... 87 | 'units','normal','pos',[.85 .02 .08 .06], ... 88 | 'callback','set(gcf,''userdata'',3)'); 89 | 90 | % Recursive call 91 | [Q,k] = quadguistep(F, a, b, tol, fa, fc, fb, varargin{:}); 92 | fcount = k + 3; 93 | 94 | % Finish 95 | title(sprintf('Q = %8.4f, fcount = %4.0f',Q,fcount)) 96 | delete(p(1:2)); 97 | delete(q(1:2)); 98 | set(q(3),'string','close','callback','close(gcf)') 99 | if nargout > 0, Qout = Q; end 100 | 101 | 102 | % --------------------------------------------------------- 103 | 104 | function [Q,fcount] = quadguistep(F,a,b,tol,fa,fc,fb,varargin) 105 | 106 | % Recursive subfunction used by quadtx. 107 | 108 | h = b - a; 109 | c = (a + b)/2; 110 | d = (a + c)/2; 111 | e = (c + b)/2; 112 | fd = F(d,varargin{:}); 113 | fe = F(e,varargin{:}); 114 | Q1 = h/6 * (fa + 4*fc + fb); 115 | Q2 = h/12 * (fa + 4*fd + 2*fc + 4*fe + fb); 116 | 117 | u1 = a:h/64:c; 118 | v1 = polyinterp([a d c],[fa fd fc],u1); 119 | u1 = [a u1 c]; 120 | v1 = [0 v1 0]; 121 | u2 = c:h/64:b; 122 | v2 = polyinterp([c e b],[fc fe fb],u2); 123 | u2 = [c u2 b]; 124 | v2 = [0 v2 0]; 125 | if (abs(Q2 - Q1) <= tol) 126 | color = [0 2/3 0]; 127 | else 128 | color = [.6 .6 .6]; 129 | end 130 | p = flipud(get(gca,'child')); 131 | x = [get(p(3),'xdata') d e]; 132 | y = [get(p(3),'ydata') fd fe]; 133 | set(p(1),'xdata',u1,'ydata',v1,'facecolor',color) 134 | set(p(2),'xdata',u2,'ydata',v2,'facecolor',color) 135 | set(p(3),'xdata',x,'ydata',y) 136 | set(gca,'xtick',sort(x),'xticklabel',[]); 137 | title(num2str(length(x))) 138 | pause(.25) 139 | while get(gcf,'userdata') == 0 140 | pause(.25) 141 | end 142 | if get(gcf,'userdata') == 1 143 | set(gcf,'userdata',0) 144 | end 145 | 146 | if (abs(Q2 - Q1) <= tol) | (get(gcf,'userdata') == 3) 147 | Q = Q2 + (Q2 - Q1)/15; 148 | fcount = 2; 149 | else 150 | [Qa,ka] = quadguistep(F, a, c, tol, fa, fd, fc, varargin{:}); 151 | [Qb,kb] = quadguistep(F, c, b, tol, fc, fe, fb, varargin{:}); 152 | Q = Qa + Qb; 153 | fcount = ka + kb + 2; 154 | end 155 | -------------------------------------------------------------------------------- /第五章 线性方程组直接解法/lugui.m: -------------------------------------------------------------------------------- 1 | function [L,U,pv,qv] = lugui(A,pivotstrat) 2 | %LUGUI Gaussian elimination demonstration. 3 | % 4 | % LUGUI(A) shows the steps in LU decomposition by Gaussian elimination. 5 | % At each step of the elimination, the pivot that would be chosen by 6 | % MATLAB's partial pivoting algorithm is shown in magenta. You can use 7 | % the mouse to pick any pivot. The pivot is shown in red, the emerging 8 | % columns of L in green, and the emerging rows of U in blue. 9 | % 10 | % LUGUI with no arguments uses a random integer test matrix. 11 | % Type 'help golub' for a description of the test matrices. 12 | % 13 | % A popup menu allows the pivot strategy to be changed dynamically. 14 | % lugui(A,'pick'), choose pivots with the mouse. 15 | % lugui(A,'diagonal'), use diagonal elements as pivots. 16 | % lugui(A,'partial'), use the largest element in the current column. 17 | % lugui(A,'complete'), use the largest element in the unreduced matrix. 18 | % 19 | % [L,U,p,q] = lugui(A,...) returns a lower triangular L, an upper 20 | % triangular U and permutation vectors p and q so that L*U = A(p,q). 21 | % 22 | % See also PIVOTGOLF. 23 | 24 | % Copyright 2014 Cleve Moler 25 | % Copyright 2014 The MathWorks, Inc. 26 | 27 | % Initialize 28 | 29 | if nargin < 2 30 | pivotstrat = 'pick'; 31 | end 32 | if nargin < 1 33 | n = 2 + ceil(6*rand); 34 | A = golub(n); 35 | end 36 | Asave = A; 37 | 38 | [m,n] = size(A); 39 | shg 40 | clf 41 | dx = 120; 42 | dy = 30; 43 | warns = warning('off','MATLAB:divideByZero'); 44 | set(gcf,'name','Lugui','menu','none','numbertitle','off', ... 45 | 'windowbuttonupfcn','set(gcf,''tag'',''pivot'')') 46 | w = (n+1)*dx; 47 | h = (m+3)*dy; 48 | pos = get(gcf,'pos'); 49 | if pos(3) < w+40 50 | pos = [pos(1)-(w+40-pos(3))/2 pos(2) w+40 pos(4)]; 51 | end 52 | if pos(4) < h+80 53 | pos = [pos(1) pos(2)-(h+80-pos(4))/2 pos(3) h+80]; 54 | end 55 | set(gcf,'pos',pos) 56 | axes('units','pixels','pos',[(pos(3)-w)/2 (pos(4)-h)/2 w h], ... 57 | 'xtick',[],'ytick',[]) 58 | box on 59 | Lcolor = [0 .65 0]; 60 | Ucolor = [0 0 .90]; 61 | Acolor = [0 0 0]; 62 | PartialPivotColor = [1 0 1]; 63 | PivotColor = [1 0 0]; 64 | ElimColor = [1 1 0]; 65 | paws = 0.02; 66 | 67 | % Each element has its own handle 68 | 69 | for j = 1:n 70 | for i = 1:m 71 | t(i,j) = text('units','pixels','string',spf(A(i,j)), ... 72 | 'fontname','courier','fontweight','bold','fontsize',14, ... 73 | 'horiz','right','color',Acolor, ... 74 | 'pos',[20+j*dx 20+(m+2-i)*dy],'userdata',[i j], ... 75 | 'buttondownfcn','set(gcf,''userdata'',get(gco,''userdata''))'); 76 | end 77 | end 78 | 79 | % Menus 80 | 81 | switch lower(pivotstrat) 82 | case 'pick', val = 1; 83 | case 'diagonal', val = 2; 84 | case 'partial', val = 3; 85 | case 'complete', val = 4; 86 | otherwise, val = 1; 87 | end 88 | pos = get(gca,'pos'); 89 | pivotstrat = uicontrol('pos',[pos(1)+pos(3)/2-75 pos(2)-35 150 20], ... 90 | 'style','pop','val',val,'fontsize',12,'back','white', ... 91 | 'string',{'Pick a pivot','Diagonal pivoting', ... 92 | 'Partial pivoting','Complete pivoting'}); 93 | quit = uicontrol('style','toggle','string','quit','fontsize',12, ... 94 | 'back','w','pos',[pos(1)+pos(3)-60 pos(2)-40 60 25],'vis','off'); 95 | 96 | % Elimination 97 | 98 | pv = 1:m; 99 | qv = 1:n; 100 | for k = 1:min(m,n) 101 | 102 | % If possible, quit early 103 | 104 | if all(all(A(k:m,k:n)==0)) | all(all(~isfinite(A(k:m,k:n)))) 105 | for l = k:min(m,n) 106 | for i = l+1:m 107 | set(t(i,l),'string',spf(A(i,l)),'color',Lcolor) 108 | drawnow 109 | end 110 | for j = l:n 111 | set(t(l,j),'string',spf(A(l,j)),'color',Ucolor) 112 | drawnow 113 | end 114 | end 115 | break 116 | end 117 | 118 | if (m == n) & (k == n) 119 | p = n; 120 | q = n; 121 | else 122 | pp = min(find(abs(A(k:m,k)) == max(abs(A(k:m,k)))))+k-1; 123 | set(t(pp,k),'color',PartialPivotColor) 124 | p = 0; 125 | q = 0; 126 | while p < k | q < k | p > m | q > n 127 | switch get(pivotstrat,'val') 128 | 129 | case 1 % Pick a pivot with mouse 130 | pq = get(gcf,'userdata'); 131 | if isequal(get(gcf,'tag'),'pivot') & ~isempty(pq) 132 | p = pq(1); 133 | q = pq(2); 134 | set(gcf,'tag','','userdata',[]) 135 | else 136 | pause(paws) 137 | end 138 | 139 | case 2 % Diagonal pivoting 140 | p = k; 141 | q = k; 142 | 143 | case 3 % Partial pivoting 144 | p = pp; 145 | q = k; 146 | 147 | case 4 % Complete pivoting 148 | [p,q] = find(abs(A(k:m,k:n)) == max(max(abs(A(k:m,k:n))))); 149 | p = p(1)+k-1; 150 | q = q(1)+k-1; 151 | end 152 | if get(quit,'value') == 1, break, end 153 | end 154 | if get(quit,'value') == 1, break, end 155 | set(t(pp,k),'color',Acolor) 156 | set(t(p,q),'color',PivotColor) 157 | end 158 | if get(quit,'value') == 1, break, end 159 | pause(10*paws) 160 | 161 | % Swap columns 162 | 163 | A(:,[q,k]) = A(:,[k,q]); 164 | qv([q,k]) = qv([k,q]); 165 | for s = .05:.05:1 166 | for i = 1:m 167 | set(t(i,k),'pos',[20+(k+s*(q-k))*dx 20+(m+2-i)*dy]) 168 | set(t(i,q),'pos',[20+(q+s*(k-q))*dx 20+(m+2-i)*dy]) 169 | end 170 | drawnow 171 | end 172 | t(:,[q,k]) = t(:,[k,q]); 173 | for i = 1:m 174 | set(t(i,k),'string',spf(A(i,k)),'userdata',[i k]) 175 | set(t(i,q),'string',spf(A(i,q)),'userdata',[i q]) 176 | end 177 | pause(10*paws) 178 | 179 | % Swap rows 180 | 181 | A([p,k],:) = A([k,p],:); 182 | pv([p,k]) = pv([k,p]); 183 | for s = .05:.05:1 184 | for j = 1:n 185 | set(t(k,j),'pos',[20+j*dx 20+(m+2-(k+s*(p-k)))*dy]) 186 | set(t(p,j),'pos',[20+j*dx 20+(m+2-(p+s*(k-p)))*dy]) 187 | end 188 | drawnow 189 | end 190 | t([p,k],:) = t([k,p],:); 191 | pause(10*paws) 192 | 193 | for j = k:n 194 | set(t(k,j),'string',spf(A(k,j)),'userdata',[k j]) 195 | set(t(p,j),'string',spf(A(p,j)),'userdata',[p j]) 196 | end 197 | pause(10*paws) 198 | 199 | % Skip step if column is all zero 200 | 201 | if all(A(k:m,k) == 0) 202 | for i = k+1:m 203 | set(t(i,k),'string',spf(A(i,k)),'color',Lcolor) 204 | drawnow 205 | end 206 | for j = k:n 207 | set(t(k,j),'string',spf(A(k,j)),'color',Ucolor) 208 | drawnow 209 | end 210 | else 211 | 212 | % Compute multipliers in L 213 | 214 | for i = k+1:m 215 | A(i,k) = A(i,k)/A(k,k); 216 | set(t(i,k),'string',spf(A(i,k)),'color',Lcolor) 217 | pause(paws) 218 | end 219 | 220 | % Elimination 221 | 222 | for j = k+1:n 223 | for i = k+1:m 224 | set(t(i,j),'color',ElimColor) 225 | pause(paws) 226 | A(i,j) = A(i,j) - A(i,k)*A(k,j); 227 | pause(paws) 228 | set(t(i,j),'string',spf(A(i,j)),'color',Acolor) 229 | end 230 | end 231 | 232 | for j = k:n 233 | set(t(k,j),'string',spf(A(k,j)),'color',Ucolor) 234 | drawnow 235 | end 236 | pause(paws) 237 | end 238 | if k < min(m,n), pause(10*paws), end 239 | end 240 | 241 | % Seperate L and U into two matrices 242 | 243 | delete(pivotstrat) 244 | 245 | for s = .1:.1:1.5 246 | for j = 1:n 247 | for i = 1:m 248 | if i <= j 249 | set(t(i,j),'pos',[20+(j+.10*s)*dx 20+(m+2-i)*dy]) 250 | else 251 | set(t(i,j),'pos',[20+(j-.10*s)*dx 20+(m+2-s-i)*dy]) 252 | end 253 | end 254 | end 255 | drawnow 256 | end 257 | 258 | % Insert ones on diagonal of L 259 | 260 | r = min(m,n); 261 | for j = 1:r 262 | text('units','pixels','string',spf(1.0), ... 263 | 'fontname','courier','fontweight','bold','fontsize',14, ... 264 | 'horiz','right','color',Lcolor, ... 265 | 'pos',[20+(j-0.15)*dx 20+(m+.5-j)*dy]); 266 | end 267 | drawnow 268 | warning(warns) 269 | 270 | if nargout > 0 271 | L = tril(A(:,1:r),-1) + eye(m,r); 272 | U = triu(A(1:r,:)); 273 | else 274 | set(gcf,'userdata',Asave) 275 | set(quit,'value',0,'string','close','fontsize',12,'callback','close(gcf)') 276 | uicontrol('pos',[pos(1)+pos(3)/2-30 pos(2)-40 80 25],'string','repeat', ... 277 | 'back','w','fontsize',12,'callback','lugui(get(gcf,''userdata''))','vis','off') 278 | end 279 | 280 | %------------------------------------------------------------ 281 | 282 | function s = spf(aij) 283 | % Subfunction to format text strings 284 | if aij == 0 285 | f = '%10.0f'; 286 | elseif (abs(aij) < 1.e-4) | (abs(aij) >= 1.e4) 287 | f = '%10.1e'; 288 | else 289 | f = '%10.4f'; 290 | end 291 | s = sprintf(f,aij); 292 | --------------------------------------------------------------------------------