fun = @(x)tan(x)-1/x;
RANGE_START = 0;
RANGE_END = 3*pi;
RANGE_STEP = pi/2;
intervals = repelem(RANGE_START:RANGE_STEP:RANGE_END,2);
intervals = reshape(intervals(2:end-1),2,[]).';
sol = NaN(size(intervals,1),1);
for ind1 = 1:numel(sol)
sol(ind1) = fzero(fun, mean(intervals(ind1,:)));
end
sol = sol(~isnan(sol)); % In case you specified more intervals than solutions.
% 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)
3 回答
要找到某个范围内函数的数值解,可以像这样使用fzero:
以上只会返回一个解决方案(
0.8603
) . 如果您需要其他解决方案,则必须多次调用fzero
. 这可以在例如循环中完成:这使:
注意:
该函数是对称的,它的根也是对称的 . 这意味着您可以仅在正间隔(例如)上求解并获得负根"for free" .
sol
中的每个其他条目都是错误的,因为这是我们渐近不连续的地方(tan
从+Inf
过渡到-Inf
),这被MATLAB错误地识别为解决方案 . 所以你可以忽略它们(即sol = sol(1:2:end);
.我从来不喜欢“盲目地”使用求解器,也就是说,没有某种合适的初始值选择方案 . 根据我的经验,盲目做事时你会发现的 Value 观也是没有背景的 . 意思是,你经常会错过解决方案,认为某些东西是解决方案,而实际上解算器爆炸了,等等 .
对于这种特殊情况,重要的是要认识到
fzero
使用数值导数来找到越来越好的近似值 . 但是,f(x) = x · tan(x) - 1
的衍生物变得越来越难以准确计算以增加x
:如您所见,
x
越大,f(x)
越接近垂直线;fzero
会简直爆炸!因此,在进入fzero
之前,必须尽可能接近解决方案 .所以,这是一种获得 good 初始值的方法 .
考虑这个功能
知道
tan(x)
有Taylor expansion:我们可以使用它来近似函数
f(x)
. 在第二学期结束后截断,我们可以写:现在,要实现的关键是
tan(x)
重复周期π
. 因此,考虑一系列功能是最有用的:对几个倍数进行评估并收集术语可得到以下推广:
在一个简单的MATLAB测试中实现所有这些:
在循环中,这可以生成下表:
如您所见,近似值基本上等于解决方案 . 对应情节:
将方程乘以
x
和cos(x)
以避免任何可以具有值0
的分母,考虑规范化函数
对于大
x
,这将越来越接近sin(x)
(或-sin(x)
为大负x
) . 实际上,绘制这个已经在视觉上是真实的,直到幅度因子为x>pi
.对于
[0,pi/2]
中的第一个根,使用第二度x^2-(1-0.5x^2)==0
的x=0
处的泰勒逼近得到x[0]=sqrt(2.0/3)
作为根近似,对于较高的那些采用正弦根x[n]=n*pi
,n=1,2,3,...
作为牛顿迭代xnext = x - f(x)/f'(x)
中的初始近似值得到