通过不动点迭代求根时输出错误
Wrong output while finding the root by Fixed Point Iteration
我有一个方程 g = @(x)(5-((5/2)*exp(x/2))-((7/2).x^2)-3*x).^1/3
,根据规范,该方程有 3 个根。但是我的输出在 x 和 g(x) 之间没有任何匹配以获得固定点。输出:
>> fpi1(g, 0.5, 20)
x0 g(x0)
0.500000000000000 0.670818823114861 - 1.161892284308499i
0.670818823114861 - 1.161892284308499i 1.281297751181495 - 1.559064591427071i
1.281297751181495 - 1.559064591427071i 1.864118571141893 - 1.621766955715062i
1.864118571141893 - 1.621766955715062i 2.320549078066838 - 1.504496934526923i
2.320549078066838 - 1.504496934526923i 2.646646533032701 - 1.316018792060223i
2.646646533032701 - 1.316018792060223i 2.870437643388612 - 1.115036747500670i
2.870437643388612 - 1.115036747500670i 3.021682102842603 - 0.927806240969038i
3.021682102842603 - 0.927806240969038i 3.123528510261589 - 0.763760920462736i
3.123528510261589 - 0.763760920462736i 3.192243659445853 - 0.624547007383635i
3.192243659445853 - 0.624547007383635i 3.238827490411373 - 0.508525243060542i
3.238827490411373 - 0.508525243060542i 3.270613725640807 - 0.412880979787002i
3.270613725640807 - 0.412880979787002i 3.292471687008435 - 0.334576282706924i
3.292471687008435 - 0.334576282706924i 3.307635263738642 - 0.270756021961336i
3.307635263738642 - 0.270756021961336i 3.318257296190301 - 0.218898831715851i
3.318257296190301 - 0.218898831715851i 3.325776161489184 - 0.176850650328430i
3.325776161489184 - 0.176850650328430i 3.331157314339334 - 0.142806525903066i
3.331157314339334 - 0.142806525903066i 3.335052371178708 - 0.115272146831085i
3.335052371178708 - 0.115272146831085i 3.337903988543196 - 0.093020017690524i
3.337903988543196 - 0.093020017690524i 3.340015124633794 - 0.075047094363536i
3.340015124633794 - 0.075047094363536i 3.341594884710001 - 0.060536697645525i
3.341594884710001 - 0.060536697645525i 3.342788954448884 - 0.048825574318716i
我做错了什么?如何解决?
%Program 1.2 Fixed-Point Iteration
%Computes approximate solution of g(x)=x
%Input: inline function g, starting guess x0,
% number of steps k
%Output: Approximate solution xc
function xc=fpi1(g,x0,k)
x(1)=x0;
for i=1:k
x(i+1)=g(x(i));
end
xc=x(k+1);
disp(' x0 g(x0)');
disp([x', g(x)']);
开始之前的一个小提示。您的 g
函数中有错字。我假设您的意思是 (7/2)*
而不是 (7/2).
。我还必须编辑您的代码以允许电源操作按元素工作:
g = @(x)(5-((5/2).*exp(x/2))-((7/2)*x.^2)-3*x).^1/3;
用这个更正后的函数做一些初始测试与你得到的相匹配。
无论如何,您使用定点迭代来求方程的根是不正确的。在我讨论你需要做什么来修复它之前,我想介绍一下定点迭代是如何工作的,这样你(以及阅读这篇文章 post 的其他人)就会明白我的出发点.
不动点迭代基于初始输入值 x0
。然后,一旦将其提交到函数中,您就会重复计算该值的输出,然后 重新使用 输出作为下一次迭代的输入。具体来说,不动点迭代方案执行此操作:
来源:Wikipedia
理想情况下,经过一些迭代后,我们希望迭代收敛到某个值 x
这样:
来源:Wikipedia
以上就是不动点的定义。这样做是为了求根(本机)不受支持,因为求方程的根与不动点应该是什么相矛盾。根的定义是 f(x) = 0
并且这是 而不是 不动点 除非 x=0
。如果要使用定点迭代求根,则必须更改函数 f
的结构方式。这将我们引向称为 Newton's Method 的经典迭代求根技术,它也使用定点迭代来求函数的根,但函数 f(x)
不同。
我不会深入探讨牛顿法的推导,但这是您在每次迭代中所做的:
来源:Wikipedia
f(x)
是函数,f'(x)
是f(x)
的导数。如果我们用新函数 g(x)
替换右侧,您将对函数 g(x)
执行定点迭代,收敛后的结果就是您要查找的根。具体来说,如果:
来源:Wikipedia
然后:
来源:Wikipedia
因此:
来源:Wikipedia
... 并且 x
是函数 f(x)
的根如果:
来源:Wikipedia
因此,您需要修改代码,使其不再使用函数句柄。它必须采用符号版本,因为您需要对函数求导。
牢记这一点,这是您需要对代码进行的修改才能使其正常工作:
%//Program 1.2 Fixed-Point Iteration via Newton's Method
%//Computes approximate root of g(x)=0
%//Input: symbolic function g, starting guess x0,
%// number of steps k
%//Output: Approximate solution xc
format long g; %// For precision
x(1)=x0;
gp = diff(g); %// Change
for i=1:k
gval = double(subs(g, 'x', x(i))); %// Change
gpval = double(subs(gp, 'x', x(i))); %// Change
x(i+1)= x(i) - (gval/gpval); %// Change
end
xc=x(k+1);
y = double(subs(g, 'x', x)); %// Change
disp(' x0 g(x0)');
disp([x' y'])
不同的是,在函数内部,您使用 diff
. Also, when you want to substitute values into the function, you need to use subs
符号化求导数,然后将结果转换为 double
。我还假设您的函数是关于变量 x
的。
倒数第三行代码将您累积的所有 x
值转换为 double
数组以供显示。
要运行这段代码,你会做:
syms x;
g = (5-((5/2)*exp(x/2))-((7/2)*x^2)-3*x)^1/3;
xc = fpi(g, 0.5, 20);
请注意,您不再需要逐元素运算符,因为我们正在处理符号方程。
我们得到:
>> fpi(g, 0.5, 20)
x0 g(x0)
0.5 -0.195021180573118
0.427814775036064 -0.0067677938874851
0.42512303212814 -9.38738903072792e-06
0.425119288112029 -1.81600035806892e-11
0.425119288104786 -5.28061163184459e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
所以其中一个根等于0.425119288104786
。右列告诉您每次迭代评估 g(x)
处的值,您可以看到它非常小...几乎为 0。这或多或少就是根的定义。
我有一个方程 g = @(x)(5-((5/2)*exp(x/2))-((7/2).x^2)-3*x).^1/3
,根据规范,该方程有 3 个根。但是我的输出在 x 和 g(x) 之间没有任何匹配以获得固定点。输出:
>> fpi1(g, 0.5, 20)
x0 g(x0)
0.500000000000000 0.670818823114861 - 1.161892284308499i
0.670818823114861 - 1.161892284308499i 1.281297751181495 - 1.559064591427071i
1.281297751181495 - 1.559064591427071i 1.864118571141893 - 1.621766955715062i
1.864118571141893 - 1.621766955715062i 2.320549078066838 - 1.504496934526923i
2.320549078066838 - 1.504496934526923i 2.646646533032701 - 1.316018792060223i
2.646646533032701 - 1.316018792060223i 2.870437643388612 - 1.115036747500670i
2.870437643388612 - 1.115036747500670i 3.021682102842603 - 0.927806240969038i
3.021682102842603 - 0.927806240969038i 3.123528510261589 - 0.763760920462736i
3.123528510261589 - 0.763760920462736i 3.192243659445853 - 0.624547007383635i
3.192243659445853 - 0.624547007383635i 3.238827490411373 - 0.508525243060542i
3.238827490411373 - 0.508525243060542i 3.270613725640807 - 0.412880979787002i
3.270613725640807 - 0.412880979787002i 3.292471687008435 - 0.334576282706924i
3.292471687008435 - 0.334576282706924i 3.307635263738642 - 0.270756021961336i
3.307635263738642 - 0.270756021961336i 3.318257296190301 - 0.218898831715851i
3.318257296190301 - 0.218898831715851i 3.325776161489184 - 0.176850650328430i
3.325776161489184 - 0.176850650328430i 3.331157314339334 - 0.142806525903066i
3.331157314339334 - 0.142806525903066i 3.335052371178708 - 0.115272146831085i
3.335052371178708 - 0.115272146831085i 3.337903988543196 - 0.093020017690524i
3.337903988543196 - 0.093020017690524i 3.340015124633794 - 0.075047094363536i
3.340015124633794 - 0.075047094363536i 3.341594884710001 - 0.060536697645525i
3.341594884710001 - 0.060536697645525i 3.342788954448884 - 0.048825574318716i
我做错了什么?如何解决?
%Program 1.2 Fixed-Point Iteration
%Computes approximate solution of g(x)=x
%Input: inline function g, starting guess x0,
% number of steps k
%Output: Approximate solution xc
function xc=fpi1(g,x0,k)
x(1)=x0;
for i=1:k
x(i+1)=g(x(i));
end
xc=x(k+1);
disp(' x0 g(x0)');
disp([x', g(x)']);
开始之前的一个小提示。您的 g
函数中有错字。我假设您的意思是 (7/2)*
而不是 (7/2).
。我还必须编辑您的代码以允许电源操作按元素工作:
g = @(x)(5-((5/2).*exp(x/2))-((7/2)*x.^2)-3*x).^1/3;
用这个更正后的函数做一些初始测试与你得到的相匹配。
无论如何,您使用定点迭代来求方程的根是不正确的。在我讨论你需要做什么来修复它之前,我想介绍一下定点迭代是如何工作的,这样你(以及阅读这篇文章 post 的其他人)就会明白我的出发点.
不动点迭代基于初始输入值 x0
。然后,一旦将其提交到函数中,您就会重复计算该值的输出,然后 重新使用 输出作为下一次迭代的输入。具体来说,不动点迭代方案执行此操作:
来源:Wikipedia
理想情况下,经过一些迭代后,我们希望迭代收敛到某个值 x
这样:
来源:Wikipedia
以上就是不动点的定义。这样做是为了求根(本机)不受支持,因为求方程的根与不动点应该是什么相矛盾。根的定义是 f(x) = 0
并且这是 而不是 不动点 除非 x=0
。如果要使用定点迭代求根,则必须更改函数 f
的结构方式。这将我们引向称为 Newton's Method 的经典迭代求根技术,它也使用定点迭代来求函数的根,但函数 f(x)
不同。
我不会深入探讨牛顿法的推导,但这是您在每次迭代中所做的:
来源:Wikipedia
f(x)
是函数,f'(x)
是f(x)
的导数。如果我们用新函数 g(x)
替换右侧,您将对函数 g(x)
执行定点迭代,收敛后的结果就是您要查找的根。具体来说,如果:
来源:Wikipedia
然后:
来源:Wikipedia
因此:
来源:Wikipedia
... 并且 x
是函数 f(x)
的根如果:
来源:Wikipedia
因此,您需要修改代码,使其不再使用函数句柄。它必须采用符号版本,因为您需要对函数求导。
牢记这一点,这是您需要对代码进行的修改才能使其正常工作:
%//Program 1.2 Fixed-Point Iteration via Newton's Method
%//Computes approximate root of g(x)=0
%//Input: symbolic function g, starting guess x0,
%// number of steps k
%//Output: Approximate solution xc
format long g; %// For precision
x(1)=x0;
gp = diff(g); %// Change
for i=1:k
gval = double(subs(g, 'x', x(i))); %// Change
gpval = double(subs(gp, 'x', x(i))); %// Change
x(i+1)= x(i) - (gval/gpval); %// Change
end
xc=x(k+1);
y = double(subs(g, 'x', x)); %// Change
disp(' x0 g(x0)');
disp([x' y'])
不同的是,在函数内部,您使用 diff
. Also, when you want to substitute values into the function, you need to use subs
符号化求导数,然后将结果转换为 double
。我还假设您的函数是关于变量 x
的。
倒数第三行代码将您累积的所有 x
值转换为 double
数组以供显示。
要运行这段代码,你会做:
syms x;
g = (5-((5/2)*exp(x/2))-((7/2)*x^2)-3*x)^1/3;
xc = fpi(g, 0.5, 20);
请注意,您不再需要逐元素运算符,因为我们正在处理符号方程。
我们得到:
>> fpi(g, 0.5, 20)
x0 g(x0)
0.5 -0.195021180573118
0.427814775036064 -0.0067677938874851
0.42512303212814 -9.38738903072792e-06
0.425119288112029 -1.81600035806892e-11
0.425119288104786 -5.28061163184459e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
0.425119288104786 1.52806116318446e-17
所以其中一个根等于0.425119288104786
。右列告诉您每次迭代评估 g(x)
处的值,您可以看到它非常小...几乎为 0。这或多或少就是根的定义。