使用 MATLAB 进行微分
Differentiation using MATLAB
我正在尝试使用 MATLAB 编写一个小程序,在该程序中我尝试区分我在不同函数中创建的函数,但我不断收到错误。
我的文件是:
newton.m:
function [ y, iter ] = newton( f, fp, x0 )
iter = 0;
xprev = x0;
x = xprev - f(xprev)/fp(xprev);
iter = iter + 1;
while abs(x-xprev) > eps*abs(x)
xprev = x;
x = x - f(x)/fp(x);
iter = iter + 1;
y = x;
end
end
f.m:
function y = f(x)
y = tan(x) - 2*x;
end
fp.m:
function y = fp(f)
y = diff(f);
end
我是运行以下的人:
[y, iter] = newton(@f, @fp, 1.4)
并获得:
Error using /
Matrix dimensions must agree.
Error in newton (line 6)
x = xprev - f(xprev)/fp(xprev);
当我检查 fp.m 中 y
的值时,我一直得到 []
。
您正在尝试使用 diff
来区分函数。开箱即用 diff
performs a difference operation between pairs of elements. You don't want this. Instead, make your f
and fp
as actual function handles. First create the symbolic definition of your function f
, then differentiate this symbolic representation using the symbolic version of diff
(which you can just call with diff
itself), then create a MATLAB function with matlabFunction
开箱即用:
%// Define symbolic variable
syms x;
%// Define function symbolically
y = tan(x) - 2*x;
%// Define function handles (numerical) to the original and derivative
f = matlabFunction(y);
fp = matlabFunction(diff(y));
%// Now call Newton's Method
[y, iter] = newton(f, fp, 1.4);
请注意,f
和 fp
已经是函数句柄。这就是 matlabFunction
returns,因此不再需要通过 @
创建句柄作为牛顿法函数的输入。
运行 对你的代码的这个修改,我得到这个作为根的初始猜测 x = 1.4
和它所花费的迭代次数:
>> format long g
>> y
y =
1.16556118520721
>> iter
iter =
8
如果符号数学工具箱丢失...
如果出于某种原因,您没有符号数学工具箱,那么我的建议将行不通。因此,您别无选择,只能使用导数的离散近似来使它起作用。然而,我们仍然可以使用我上面写的代码,但是 fp
必须以不同的方式定义。
如果你还记得,导数的定义是这样的:
为了让它在离散情况下工作,你使 Δx
非常小......例如 1e-10
。
因此,您可以使用匿名函数来代替:
%// Define function
f = @(x) tan(x) - 2*x;
%// Define derivative
h = 1e-10;
fp = @(x) (f(x + h) - f(x)) / h;
%// Now call Newton's Method
[y, iter] = newton(f, fp, 1.4);
有了这个,我得到:
>> format long g;
>> y
y =
1.16556118520721
>> iter
iter =
8
我会说这非常接近!
我正在尝试使用 MATLAB 编写一个小程序,在该程序中我尝试区分我在不同函数中创建的函数,但我不断收到错误。
我的文件是:
newton.m:
function [ y, iter ] = newton( f, fp, x0 )
iter = 0;
xprev = x0;
x = xprev - f(xprev)/fp(xprev);
iter = iter + 1;
while abs(x-xprev) > eps*abs(x)
xprev = x;
x = x - f(x)/fp(x);
iter = iter + 1;
y = x;
end
end
f.m:
function y = f(x)
y = tan(x) - 2*x;
end
fp.m:
function y = fp(f)
y = diff(f);
end
我是运行以下的人:
[y, iter] = newton(@f, @fp, 1.4)
并获得:
Error using /
Matrix dimensions must agree.Error in newton (line 6) x = xprev - f(xprev)/fp(xprev);
当我检查 fp.m 中 y
的值时,我一直得到 []
。
您正在尝试使用 diff
来区分函数。开箱即用 diff
performs a difference operation between pairs of elements. You don't want this. Instead, make your f
and fp
as actual function handles. First create the symbolic definition of your function f
, then differentiate this symbolic representation using the symbolic version of diff
(which you can just call with diff
itself), then create a MATLAB function with matlabFunction
开箱即用:
%// Define symbolic variable
syms x;
%// Define function symbolically
y = tan(x) - 2*x;
%// Define function handles (numerical) to the original and derivative
f = matlabFunction(y);
fp = matlabFunction(diff(y));
%// Now call Newton's Method
[y, iter] = newton(f, fp, 1.4);
请注意,f
和 fp
已经是函数句柄。这就是 matlabFunction
returns,因此不再需要通过 @
创建句柄作为牛顿法函数的输入。
运行 对你的代码的这个修改,我得到这个作为根的初始猜测 x = 1.4
和它所花费的迭代次数:
>> format long g
>> y
y =
1.16556118520721
>> iter
iter =
8
如果符号数学工具箱丢失...
如果出于某种原因,您没有符号数学工具箱,那么我的建议将行不通。因此,您别无选择,只能使用导数的离散近似来使它起作用。然而,我们仍然可以使用我上面写的代码,但是 fp
必须以不同的方式定义。
如果你还记得,导数的定义是这样的:
为了让它在离散情况下工作,你使 Δx
非常小......例如 1e-10
。
因此,您可以使用匿名函数来代替:
%// Define function
f = @(x) tan(x) - 2*x;
%// Define derivative
h = 1e-10;
fp = @(x) (f(x + h) - f(x)) / h;
%// Now call Newton's Method
[y, iter] = newton(f, fp, 1.4);
有了这个,我得到:
>> format long g;
>> y
y =
1.16556118520721
>> iter
iter =
8
我会说这非常接近!