我从不喜欢“盲目地”使用求解器,也就是说,没有某种体面的初始值选择方案。根据我的经验,你在盲目做事时会发现的价值观也没有上下文。意思是,你经常会错过解决方案,认为某些东西是解决方案,而实际上解决方案爆炸了,等等。
对于这种特殊情况,重要的是要意识到fzero 使用数值导数来找到越来越好的近似值。但是,随着x 的增加,f(x) = x · tan(x) - 1 的导数越来越难以准确计算:
如您所见,x 越大,f(x) 越接近垂直线; fzero 会爆炸!因此,在输入fzero 之前,必须尽可能接近 得到一个估计值。
所以,这是一种获得良好初始值的方法。
考虑函数
f(x) = x · tan(x) - 1
知道tan(x) 有Taylor expansion:
tan(x) ≈ x + (1/3)·x³ + (2/15)·x⁵ + (7/315)·x⁷ + ...
我们可以用它来近似函数f(x)。在第二项之后截断,我们可以写成:
f(x) ≈ x · (x + (1/3)·x³) - 1
现在,要实现的关键是 tan(x) 与句点 π 重复。因此,考虑函数族是最有用的:
fₙ(x) ≈ x · ( (x - n·π) + (1/3)·(x - n·π)³) - 1
评估几个倍数并收集术语得出以下概括:
f₀(x) = x⁴/3 - 0π·x³ + ( 0π² + 1)x² - (0π + (0π³)/3)·x - 1
f₁(x) = x⁴/3 - 1π·x³ + ( 1π² + 1)x² - (1π + (1π³)/3)·x - 1
f₂(x) = x⁴/3 - 2π·x³ + ( 4π² + 1)x² - (2π + (8π³)/3)·x - 1
f₃(x) = x⁴/3 - 3π·x³ + ( 9π² + 1)x² - (3π + (27π³)/3)·x - 1
f₄(x) = x⁴/3 - 4π·x³ + (16π² + 1)x² - (4π + (64π³)/3)·x - 1
⋮
fₙ(x) = x⁴/3 - nπ·x³ + (n²π² + 1)x² - (nπ + (n³π³)/3)·x - 1
在一个简单的 MATLAB 测试中实现所有这些:
% Replace this with the whole number of pi's you want to
% use as offset
n = 5;
% The coefficients of the approximating polynomial for this offset
C = @(npi) [1/3
-npi
npi^2 + 1
-npi - npi^3/3
-1];
% Find the real, positive polynomial roots
R = roots(C(n*pi));
R = R(imag(R)==0);
R = R(R > 0);
% And use these as initial values for fzero()
x_npi = fzero(@(x) x.*tan(x) - 1, R)
在一个循环中,这可以产生下表:
% Estimate (polynomial) Solution (fzero)
0.889543617524132 0.860333589019380 0·π
3.425836967935954 3.425618459481728 1·π
6.437309348195653 6.437298179171947 2·π
9.529336042900365 9.529334405361963 3·π
12.645287627956868 12.645287223856643
15.771285009691695 15.771284874815882
18.902410011613000 18.902409956860023
22.036496753426441 22.036496727938566 ⋮
25.172446339768143 25.172446326646664
28.309642861751708 28.309642854452012
31.447714641852869 31.447714637546234
34.586424217960058 34.586424215288922 11·π
如您所见,近似值基本上等于解。对应情节: