我怎样才能在 MATLAB 中得到这个方程的所有解?
How can I get all solutions to this equation in MATLAB?
我想解下面的方程:tan(x) = 1/x
我做了什么:
syms x
eq = tan(x) == 1/x;
sol = solve(eq,x)
但这只给了我解的一个数值近似值。之后我阅读了以下内容:
[sol, params, conds] = solve(eq, x, 'ReturnConditions', true)
但这告诉我它找不到明确的解决方案。
如何在给定范围内找到该方程的数值解?
要在某个范围内找到函数的数值解,您可以像这样使用 fzero
:
fun = @(x)x*tan(x)-1; % Multiplied by x so fzero has no issue evaluating it at x=0.
range = [0 pi/2];
sol = fzero(fun,range);
以上 return 只是一种解决方案 (0.8603
)。如果您需要其他解决方案,则必须多次调用 fzero
。例如,这可以在一个循环中完成:
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.
给出:
[0.86033358901938;
1.57079632679490; % Wrong
3.42561845948173;
4.71238898038469; % Wrong
6.43729817917195;
7.85398163397449] % Wrong
注意:
- 函数是对称的,它的根也是。这意味着您可以仅在正区间上求解(例如)并获得负根 "for free".
sol
中的每个其他条目都是错误的,因为这是我们有渐近不连续的地方(tan
从 +Inf
到 -Inf
的过渡),这是被错误识别的MATLAB 作为解决方案。所以你可以忽略它们(即 sol = sol(1:2:end);
.
我从来不喜欢使用求解器 "blindly",也就是说,没有某种合适的初始值选择方案。根据我的经验,你在盲目做事时会发现的价值观也将没有背景。这意味着,您经常会错过解决方案,认为某事是解决方案,而实际上求解器爆炸了,等等。
对于这种特殊情况,重要的是要认识到 fzero
使用数值导数来找到越来越好的近似值。但是,f(x) = x · tan(x) - 1
的导数越来越难以准确计算以增加 x
:
可以看出,x
越大,f(x)
越接近垂直线; fzero
简直要爆炸了!因此,在进入 fzero
.
之前,必须尽可能 接近 解决方案。
所以,这是获得 good 初始值的方法。
考虑函数
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)
在一个循环中,这会产生以下结果table:
% 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·π
如你所见,近似值基本上等于解。对应剧情:
将等式乘以 x
和 cos(x)
以避免任何可能具有值 0
、
的分母
f(x)=x*sin(x)-cos(x)==0
考虑归一化函数
h(x)=(x*sin(x)-cos(x)) / (abs(x)+1)
对于大 x
,这将越来越接近 sin(x)
(或 -sin(x)
对于大负 x
)。事实上,绘制此图在视觉上已经是真实的,达到幅度因子,x>pi
。
对于[0,pi/2]
中的第一个根,使用x=0
二阶x^2-(1-0.5x^2)==0
处的泰勒近似得到x[0]=sqrt(2.0/3)
作为根近似,对于较高的取正弦根 x[n]=n*pi
、n=1,2,3,...
作为牛顿迭代 xnext = x - f(x)/f'(x)
中的初始近似值得到
n initial 1. Newton limit of Newton
0 0.816496580927726 0.863034004302817 0.860333589019380
1 3.141592653589793 3.336084918413964 3.425618459480901
2 6.283185307179586 6.403911810682199 6.437298179171945
3 9.424777960769379 9.512307014150883 9.529334405361963
4 12.566370614359172 12.635021895208379 12.645287223856643
5 15.707963267948966 15.764435036320542 15.771284874815882
6 18.849555921538759 18.897518573777646 18.902409956860023
7 21.991148575128552 22.032830614521892 22.036496727938566
8 25.132741228718345 25.169597069842926 25.172446326646664
9 28.274333882308138 28.307365162331923 28.309642854452012
10 31.415926535897931 31.445852385744583 31.447714637546234
11 34.557519189487721 34.584873343220551 34.586424215288922
我想解下面的方程:tan(x) = 1/x
我做了什么:
syms x
eq = tan(x) == 1/x;
sol = solve(eq,x)
但这只给了我解的一个数值近似值。之后我阅读了以下内容:
[sol, params, conds] = solve(eq, x, 'ReturnConditions', true)
但这告诉我它找不到明确的解决方案。
如何在给定范围内找到该方程的数值解?
要在某个范围内找到函数的数值解,您可以像这样使用 fzero
:
fun = @(x)x*tan(x)-1; % Multiplied by x so fzero has no issue evaluating it at x=0.
range = [0 pi/2];
sol = fzero(fun,range);
以上 return 只是一种解决方案 (0.8603
)。如果您需要其他解决方案,则必须多次调用 fzero
。例如,这可以在一个循环中完成:
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.
给出:
[0.86033358901938;
1.57079632679490; % Wrong
3.42561845948173;
4.71238898038469; % Wrong
6.43729817917195;
7.85398163397449] % Wrong
注意:
- 函数是对称的,它的根也是。这意味着您可以仅在正区间上求解(例如)并获得负根 "for free".
sol
中的每个其他条目都是错误的,因为这是我们有渐近不连续的地方(tan
从+Inf
到-Inf
的过渡),这是被错误识别的MATLAB 作为解决方案。所以你可以忽略它们(即sol = sol(1:2:end);
.
我从来不喜欢使用求解器 "blindly",也就是说,没有某种合适的初始值选择方案。根据我的经验,你在盲目做事时会发现的价值观也将没有背景。这意味着,您经常会错过解决方案,认为某事是解决方案,而实际上求解器爆炸了,等等。
对于这种特殊情况,重要的是要认识到 fzero
使用数值导数来找到越来越好的近似值。但是,f(x) = x · tan(x) - 1
的导数越来越难以准确计算以增加 x
:
可以看出,x
越大,f(x)
越接近垂直线; fzero
简直要爆炸了!因此,在进入 fzero
.
所以,这是获得 good 初始值的方法。
考虑函数
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)
在一个循环中,这会产生以下结果table:
% 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·π
如你所见,近似值基本上等于解。对应剧情:
将等式乘以 x
和 cos(x)
以避免任何可能具有值 0
、
f(x)=x*sin(x)-cos(x)==0
考虑归一化函数
h(x)=(x*sin(x)-cos(x)) / (abs(x)+1)
对于大 x
,这将越来越接近 sin(x)
(或 -sin(x)
对于大负 x
)。事实上,绘制此图在视觉上已经是真实的,达到幅度因子,x>pi
。
对于[0,pi/2]
中的第一个根,使用x=0
二阶x^2-(1-0.5x^2)==0
处的泰勒近似得到x[0]=sqrt(2.0/3)
作为根近似,对于较高的取正弦根 x[n]=n*pi
、n=1,2,3,...
作为牛顿迭代 xnext = x - f(x)/f'(x)
中的初始近似值得到
n initial 1. Newton limit of Newton
0 0.816496580927726 0.863034004302817 0.860333589019380
1 3.141592653589793 3.336084918413964 3.425618459480901
2 6.283185307179586 6.403911810682199 6.437298179171945
3 9.424777960769379 9.512307014150883 9.529334405361963
4 12.566370614359172 12.635021895208379 12.645287223856643
5 15.707963267948966 15.764435036320542 15.771284874815882
6 18.849555921538759 18.897518573777646 18.902409956860023
7 21.991148575128552 22.032830614521892 22.036496727938566
8 25.132741228718345 25.169597069842926 25.172446326646664
9 28.274333882308138 28.307365162331923 28.309642854452012
10 31.415926535897931 31.445852385744583 31.447714637546234
11 34.557519189487721 34.584873343220551 34.586424215288922