数学建模社区-数学中国

标题: 比较通过符号计算得到的导数和通过数值差分方法计算得到的导数的结果 [打印本页]

作者: 2744557306    时间: 2024-9-26 17:21
标题: 比较通过符号计算得到的导数和通过数值差分方法计算得到的导数的结果
h=0.05; x=0:h:pi; syms x1; y=sin(x1)/(x1^2+4*x1+3);
" n. {1 o3 B+ U) r% K$ G3 |yy1=diff(y); f1=subs(yy1,x1,x);   % 求各阶导数的解析解与对照数据9 N  t+ K! s* z' |. C7 d; J
yy2=diff(yy1); f2=subs(yy2,x1,x); yy3=diff(yy2); f3=subs(yy3,x1,x);
5 g: K, i3 |, n  ryy4=diff(yy3); f4=subs(yy4,x1,x);
; G7 V2 R4 v* i2 B6 t4 m5 e. b- P' e4 ]
y=sin(x)./(x.^2+4*x+3);   % 生成已知数据点9 T0 z2 i) O+ d1 b0 I  K3 S
[y1,dx1]=diff_ctr(y,h,1); subplot(221),plot(x,f1,dx1,y1,':');6 y/ I  a! ^' H. ?
[y2,dx2]=diff_ctr(y,h,2); subplot(222),plot(x,f2,dx2,y2,':')4 }; s$ q# O# B6 M3 Z) [
[y3,dx3]=diff_ctr(y,h,3); subplot(223),plot(x,f3,dx3,y3,':');/ D! W8 N3 U& m0 h. h+ D& n
[y4,dx4]=diff_ctr(y,h,4); subplot(224),plot(x,f4,dx4,y4,':')6 N+ L. w8 D1 o, S6 H( K

6 x; Y0 z! @& p+ l% onorm((y4-f4(4:60))./f4(4:60))
4 i6 o' f! Y: Q6 N这段MATLAB代码旨在比较通过符号计算得到的导数和通过数值差分方法计算得到的导数的结果。以下是对代码的逐步解析:* q5 ?/ q2 c& T! P7 @# m0 ~
9 `# h) R, J8 y6 Y( @3 q

& d# @# V+ _# H% [" v### 1. 定义和设置, ~# G, |- S, \3 A0 x0 g; x' B
```matlab6 h# _3 p$ ?2 t) X3 ^
h = 0.05; ( L" j. M4 |; i) S
x = 0:h:pi; ) H2 ~1 }$ H& H/ p* L
syms x1; , F2 n% s/ f, K2 b
y = sin(x1) / (x1^2 + 4*x1 + 3);
) x6 n$ B* u9 Z! }/ N+ u```
+ I( [2 J( B. g) s0 Z3 X) a- `h = 0.05;` 定义了一个小步长 `h`,用于生成数据点。* P- u; C# p+ K- Y2 }+ j4 D
- `x = 0:h:pi;` 生成从0到π的等间距点。
7 m; I0 x" `) ?- `syms x1;` 定义了一个符号变量 `x1`。
1 \6 Y" O' i9 ?% l9 i8 E- `y = sin(x1) / (x1^2 + 4*x1 + 3);` 定义了符号函数 `y`,这是一个关于 `x1` 的函数。
) t/ h3 u) x1 s1 J/ m) e
" Q' I# c5 w2 }6 q$ s7 h

: e7 Y0 e; }1 g9 j/ |  e# h### 2. 计算导数
! N$ d0 ~- O$ s```matlab' M# N! U5 B) T
yy1 = diff(y);
4 N+ |1 }0 w" i0 t; K, S, vf1 = subs(yy1, x1, x);
+ V1 K6 O5 |) Y. }```( E5 z2 D, G# R% Y$ K) p$ h
- `yy1 = diff(y);` 计算函数 `y` 的第一阶导数。
1 b9 D6 f* m" c3 T4 S7 ^' D1 y- `f1 = subs(yy1, x1, x);` 使用 `subs` 将导数中的符号变量 `x1` 替换为具体的 `x` 值,得到导数的值,储存在 `f1` 中。
, S: k2 a5 c- K2 P, ^' N& p- M% \) ]8 c8 W: h. T

4 T' r2 c& o# N5 G" K5 r1 h对后续导数的计算重复相同的操作:
& }, |7 x6 z9 L( ?  }5 [' h0 x9 A```matlab
6 F3 u2 N  W' `2 x  F3 E  B! Nyy2 = diff(yy1); ( M% a; t0 h; N. W: s1 @1 \  @
f2 = subs(yy2, x1, x); 8 r* Q# M% K. l6 R3 L
yy3 = diff(yy2);
9 E. f- R9 O+ ]$ l& qf3 = subs(yy3, x1, x);
( n2 [/ u& i+ P. C6 G- }! gyy4 = diff(yy3); , f* J: f& }' b  T2 \1 H3 [
f4 = subs(yy4, x1, x);! Y1 t4 J6 N$ I2 i& ~3 F
```
7 H4 N9 T; v" O$ a+ V6 P- 上述代码计算了 `y` 的第二、第三和第四阶导数,并相应地进行了替换得到了 `f2`、`f3` 和 `f4`。
* C3 \. b& c% @4 L8 I) ?  H1 }- z( _: f
3 Z& I1 y* B0 t% v% n1 B4 v; z
### 3. 生成已知数据点. T' p# V' k3 y" a. G4 k3 `: `  |7 s  E
```matlab
) B8 C. J* e; c" L" W7 @8 B3 cy = sin(x) ./ (x.^2 + 4*x + 3);
4 E3 \( d4 x+ ^! }$ _```: Y9 z  y/ f# P' T4 e! Y% S
- 计算 `y` 的值,将 `x` 中的每个元素代入,生成已知数据点。
$ k" y4 N' k4 R& W; W" `+ b0 u
$ O7 \; S8 K2 u# I

  o4 [4 t$ j! I3 _### 4. 使用差分方法计算导数
! V+ t* `, `9 ^2 X$ I8 @7 S! {1 c以下是使用数值方法计算导数的步骤,假设 `diff_ctr` 函数已经定义并实现:
; o% I! u! H" r- l& }3 c+ d: z- t3 t* I! r9 g, H

( P0 t0 m- M6 ~+ {  o6 A3 K0 R8 K```matlab
3 ^; \8 n; @& Q" b; P[y1, dx1] = diff_ctr(y, h, 1); ) X0 F8 x% V5 g0 j7 m' }
subplot(221), plot(x, f1, dx1, y1, ':');
& u, C8 M4 E$ ^0 |0 b4 w[y2, dx2] = diff_ctr(y, h, 2);
. ^. h9 t: x( n+ U: lsubplot(222), plot(x, f2, dx2, y2, ':');
6 |3 G$ x0 p, ?& I5 [7 l; Z[y3, dx3] = diff_ctr(y, h, 3); 3 U* a* W! B1 W
subplot(223), plot(x, f3, dx3, y3, ':');% W) W, T- ?: `4 c5 Y
[y4, dx4] = diff_ctr(y, h, 4);
% K4 M4 g+ c4 `# E2 O* nsubplot(224), plot(x, f4, dx4, y4, ':');
- {: G4 a! J+ Y- D: \1 v, r  x```
( R; I  l9 r0 B3 i: D* f; d1 K- `diff_ctr(y, h, n)` 函数可能是一个自定义的函数,用来通过中心差分方法计算函数 `y` 的 `n` 阶导数。* n) f, e6 s) q3 {
- `subplot` 和 `plot` 用于可视化结果,将每个计算的导数和数值差分结果绘制在不同的子图中。: P8 c% c% e5 W) X
1 M& S+ V6 g. ?* D

- Y! C1 t; W& k8 j### 5. 计算误差的规范化9 @0 E; r& B3 Q9 F& L  x
```matlab4 o, Q" @- \" m6 c7 K( s% F
norm((y4 - f4(4:60)) ./ f4(4:60))
9 G7 }. Z- v& f' e- K4 y```' A+ \" y7 Y1 W. Q- P% n! C: H
- `norm(...)` 用于计算向量的范数,这里比较后处理的数值导数 `y4` 和符号计算的导数 `f4(4:60)`,以计算相对误差。
$ g. m) C1 g8 j& Q9 Q) F1 O- 通过这种方法,用户可以评估数值计算的精度。& l1 e+ @' A/ W: B! l' K

1 U8 ]- [4 O7 o$ ~, D
) n  w" Z! r# w1 s9 U2 C' l, Q
### 总结7 u$ ^8 ]2 G. f+ `* O
这段代码的主要目标是通过符号计算和中心差分法计算函数的导数,并绘制出它们的比较图。最终的规范化误差提供了一种衡量数值方法精度的手段。这种方法对理解和验证数值微分的重要性以及与解析解的比较相当有用。
3 N2 \' ^6 E2 P$ C2 ^
/ o* J. k& H/ C0 @
0 h. K5 {; k: Y9 e! a, f* {" n  }; D
( M9 {  A% Q0 Q( R
7 K9 b1 f! Q7 q7 ~





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5