我有一段带有while循环的代码。该循环在某些条件下会发散,从而产生无限循环。
我想检查循环是否发散并以优雅高效的方式打破循环。
对此的解决方案是检查循环的每个输出,保存它,并将其与先前计算的循环输出进行比较。
这是代码:
ai = 0;
ai_old = 100;
iteration = 0;
CDeff = 0;
while abs(ai - ai_old)>2*10^-1 % Get induced angle of attack
iteration = iteration +1;
ai_old = ai;
Cleff = (Clp * cosd(ai)^2 + CDeff * sind(ai) )/cosd(ai);
Veff = Vp/cosd(ai);
Re_eff = Reinf * Veff/Vinf * cp/c;
Meff = Mp/cosd(ai);
if iteration ==1
AFdata(:,2) = AFdata(:,2)/cosd(SweepQC);
end
[~,a_eff,CDeff] = obj.ConstantVortex(AFdata,[],Cleff,Meff);
ai = -a_eff + (AOA + Twists(zz))/cosd(SweepQC);
end
此处,ai
使用函数obj.ConstantVortex
计算,并与之前计算的ai
进行比较。当差异足够小时,while循环终止。
但是,初始ai
和计算ai
之间的差异可能会随着每次迭代而增加。
我该怎么检查?并相应地打破循环?
谢谢
答案 0 :(得分:0)
一种解决方案是保持最后的差异或最小差异并比较当前的差异。例如,您可以使用变量ai_older
并使用它。你可以添加
ai_older = 1000;
在你的while循环之前然后有
ai_older = ai_old;
ai_old = ai;
并将while
条件更改为
while abs(ai - ai_old)>2*10^-1 && abs(ai - ai_old) < abs(ai_old - ai_older)
现在你可以避免分歧。但是,我并不完全了解您的问题,也不确定是否需要使用abs
。
正如我之前提到的,根据您的问题,您可能希望保持最小差异,并将当前的一个与之比较。
答案 1 :(得分:0)
这种情况的典型解决方案是存储更多以前的值,并监控一段时间内的行为。因此,您将使用:
而不是ai_old
ai = 0;
num_prev = 5; % how many previous results to check
ai_prev = zeros(1,num_prev);
iteration = 0;
while abs(ai - ai_prev(end))>2*10^-1
iteration = iteration+1;
% your loop code goes here
% now update the array of previous values
ai_prev = circshift(ai_prev,[0 -1]);
ai_prev(end) = ai;
if iteration > num_prev && all(sign(diff(ai_prev)))
% the slope of the previous five results is positive, so exit
break
end
end
您可以更改先前结果的数量,并使用适当的函数来检查ai_prev
中数据的中断条件以进行计算。例如,您可能希望对先前的结果进行一些平均,或使用与diff()
不同的函数。