在Matlab或Octave中使用fzero,避免使用循环和复杂的解决方案

时间:2016-05-01 10:58:15

标签: matlab octave equation-solving nonlinear-functions

我正在使用fzero函数来根据一个参数求解非线性方程 而且我对我的方法不满意。我有这些问题:

1)可以避免参数循环吗?

2)为了避免复杂的解决方案,我首先必须预先计算fzero的有效间隔。    这里有更好的解决方案吗?

如果我减小参数步长,执行时间会变慢。如果我不预先计算 间隔我得到一个错误“间隔端点的函数值必须是有限的和真实的。” 在Matlab和Octave中的“fzero:不是一个有效的初始包围”。

这是代码

% solve y = 90-asind(n*(sind(90-asind(sind(a0)/n)-y)))

% set the equation paramaters
n=1.48; a0=0:0.1:60;

% loop over a0
for i = 1:size(a0,2)

  % for each a0 find where the argument of outer asind() 
  % will not give complex solutions, i.e. argument is between 1 and -1 

  fun1 = @(y) n*(sind(90-asind(sind(a0(i))/n)-y))-0.999;
  y1 = fzero(fun1,[0 90]);  
  fun2 = @(y) n*(sind(90-asind(sind(a0(i))/n)-y))+0.999;
  y2 = fzero(fun2,[0 90]);


  % use y1, y2 as limits in fzero interval

  fun3 = @(y) 90-asind(n*(sind(90-asind(sind(a0(i))/n)-y)))-y;
  y(i) = fzero(fun3, [y1 y2]);

end

% plot the result
figure; plot(y); grid minor;
xlabel('Incident ray angle [Deg]');
ylabel('Lens surface tangent angle');

1 个答案:

答案 0 :(得分:1)

使用Matlab,我通过以下简化循环获得了下图。

for i = 1:size(a0,2)
  fun3 = @(y) sind(90-y) - n*(sind(90-asind(sind(a0(i))/n)-y));
  y(i) = fzero(fun3, [0,90]);
end

不同之处在于等式:我用sin(90-y)=某物取代了90-y = asind(某物)。当“something”的绝对值大于1时,由于asind的复杂值,前一版本会抛出错误。后者正常进行,认识到这不是一个解决方案(sin(90-y)不能等于大于1的东西)。

不需要预先计算支架,[0,90]简单地工作。我做的另一个更改是使用plot(a0,y)而不是plot(y),以获得正确的水平轴。

你无法避免for循环,也不用担心。向量化意味着消除循环,其中内容是一个低级操作,可以通过在某个C数组上操作来完成 en masse 。但是fzero完全不是那样的。如果代码需要很长时间才能运行,那是因为解决一堆方程需要很长时间,而不是因为有一个for循环。

plot