何时在Matlab中使用assert()?

时间:2014-11-26 22:04:44

标签: matlab exception-handling assert

由于Matlab被解释,通常会在执行函数签名的函数开头花费大量时间。例如

if nargin ~= 2; error('must provide two input args a and b'); end
if a < 0||a ~=floor(a); error('input arg1 must be positive non-zero integer'); end 
if ~isa(b,'cell') ...

使用Matlab的assert()代替它更好吗?如果没有,何时适合在Matlab中使用assert()?

关于在生产代码here中使用assert的讨论非常多,但我不确定这是否适用于解释代码。同样,另一个很好的讨论here和我同意@Dan Dyer关于断言表达对当前状态的信念。然而,看一下类似的Python here讨论的人说,只使用断言来应对永远不会发生的情况(例如异常情况的例外情况),这有点矛盾了w.r.t。以前的参考文献。

也许这更像是一个关于断言在解释语言中起作用的问题而不是关于Matlab的问题。

3 个答案:

答案 0 :(得分:4)

在大多数情况下,

之间没有区别
assert(X,...)

if (~X)
    error(...)
end

你在他们之间的选择是方便或风格的问题。

基于MATLAB的项目中非生产和生产代码之间的区别通常与基于其他语言的项目中的区别不同。

这部分是因为,正如你所说,MATLAB通常是解释而不是编译;虽然可以使用MATLAB Compiler或Builder产品生成应用程序,虽然不严格&#34;编译&#34;,但是没有可见的源代码且无法调试。对于那些类型的应用程序,您需要像编译语言一样谨慎处理异常和错误。

部分原因还在于&#34;生产&#34;对于使用MATLAB的项目而言,通常意味着与使用其他语言的项目不同的东西;例如,它可能意味着MATLAB代码自动转换为C以部署到汽车引擎控制器,或者它可能意味着某些MATLAB代码正在运行财务预测模型并将结果写入生产数据库。

有一种特殊情况应该使用assert而不是if..error..end,这是因为您使用MATLAB Coder从MATLAB代码生成C代码。 MATLAB编码器检查MATLAB代码中的assert语句,以推断它需要转换为C的变量的属性,并且如果它可以假设有关您断言的变量的事实(例如数组大小和类型),则可以生成更好的C代码。

最后一点:对于你提到的具体活动,强制执行函数签名,我不会使用任何方法 - inputParser通常更健壮和一致(虽然有点冗长),但更重要的是它鼓励你首先设计好功能签名。

答案 1 :(得分:2)

MATLAB处理断言的方式意味着,从用户的角度来看,语句之间没有区别:

if error_check == false
    error('function:state','Error message');
end

assert(error_check==false,'function:state','Error message');

两者都会向用户显示相同的输出,并且相同的数据存储在lasterr中。两者都被try-catch块捕获。基于一个非常快速和肮脏的测试,我会暂时声称asserterror慢约5%(尽管这并没有真正对大型方案产生巨大影响) 。因此,唯一真正的区别在于代码的程序员/维护者,这使其成为一种风格选择。

asserterror都有其优缺点。 assert看起来更清洁,占用的空间更少,但乍看之下并不是必需的。对于我个人使用,我更喜欢error的情况,因为我可以在错误调用的行上设置一个断点,并且只有在即将抛出错误时它才会中断 - 这可以&#39;可以像使用断言消息一样轻松完成(您可以使用dbstop in file if error,但这可能有其自身的问题)。我还可以在if-statement中粘贴调试代码,以便在抛出错误之前打印有关程序状态的信息。

答案 2 :(得分:2)

此问题的另一个视角是运行时间。 通常,您希望您的代码能够正常运行。这意味着你不关心Matlab产生错误所需的几毫秒,而只关心逻辑测试。

这是我用来比较的代码:

function o=test

a = 2;
o = [0 0];

tic;
if a~=2
error('a is not 2')
end
o(1) = toc;


tic
assert(a==2,'a is not 2')
o(2) = toc;

现在,让我们运行这个功能足够的时间来获得好的统计数据:

for i=1:10000
o(i,:) = test;
end
mean(o)

和结果:

ans =

1.0e-05 *

0.0088 0.3548

底线:

断言比if-else慢得多。