在Matlab中验证两个相关输入的最佳实践

时间:2017-10-19 12:26:39

标签: matlab validation input

我对使用多个输入的Matlab函数中的输入验证的最佳实践有疑问。这有点哲学。我在论坛中四处看了看,我还没有看到对此的全面讨论。我关心验证条件涉及两个或更多输入变量的情况。这是一个例子。

假设我用两个输入a和b编写一个函数。我知道输入必须满足条件

a > 0b > 0

如果我想验证这些输入,我通常会编写一个这样的函数(仅用于说明目的,函数的作用并不重要):

% My function
function [result] = myLogSum(a,b)

% Create an input parser
p = inputParser;
% Add required inputs with validation
isPositive = @(x) all(x>0);
addRequired(p, 'a', isPositive);
addRequired(p, 'b', isPositive);
% Parse the inputs
parse(p,a,b);

% Calculate the log sum
result = log(a) + log(b);

end

但现在假设a和b是数组,我还需要检查它们是否大小相同:

all(size(a) == size(b)) == true

有没有办法用输入解析器处理这种情况?如果没有,处理这个问题的最佳方法是什么?

我可以想到四种解决方案,但我无法弄清楚哪种解决方案最好。

1)我应该将a和b混合在sumInput形式的单个输入单元格变量{a,b}中,并为单元格数组编写自定义验证函数吗?这没关系,但我不知道将输入汇总到一起是否总是很好的做法。在这里,能够编写myLogSum(a,b)而不是myLogSum(sumInput)似乎很自然。

2)或者在这种情况下,我应该在函数中编写输入验证的这一部分,即修改上面的代码如下:

% My function
function [result] = myLogSum(a,b)

% Create an input parser
p = inputParser;
% Add required inputs with validation
isPositive = @(x) all(x>0);
addRequired(p, 'a', isPositive);
addRequired(p, 'b', isPositive);
% Parse the inputs
parse(p,a,b);

% Check that the input arrays have the same size
if ~all(size(a)==size(b))
   message = 'The arrays a and b must have the same size.';
   error(message);
end

% Calculate the log sum
result = log(a) + log(b);

end

这也很好,但它使得验证有点不均匀和不美观,因为现在我输入a和b以不同的方式和不同的原因进行了两次验证。

3)我应该放弃输入解析器并编写自己的验证函数,如下所示:

Best practice when validating input in MATLAB

但我非常喜欢输入解析器,因为它是管理选项的一种巧妙方法。

4)当程序到达最后一行result = log(a) + log(b)并且数组大小不匹配时,我可以让Matlab自己处理错误。但不知怎的,我觉得从长远来看,这是在惹麻烦。

如果您有Matlab的经验,请告诉我您认为当两个输入相关时您认为最强大和最全面的验证策略。

2 个答案:

答案 0 :(得分:3)

没有什么可以阻止您调用parse一次,然后添加新输入并再次调用parse - 此时您可以在验证中使用先前解析的值功能。 validateattributes函数在此处用于构建具有多个条件的验证函数。例如:

% My function
function [result] = myLogSum(a,b)

% Create an input parser
p = inputParser;
% Add required inputs with validation
addRequired(p, 'a', @(x) validateattributes(x, {'numeric'}, {'>', 0}));
% Check the first input was valid
p.parse(a);
addRequired(p, 'b', @(x) validateattributes(x, {'numeric'}, {'>', 0, 'size', size(a)}));
% Parse the inputs
p.parse(a,b);

% Calculate the log sum
result = log(a) + log(b);

end

validateattributes还会为您生成合理解释的错误消息:

>> myLogSum(30, 40)

ans =

    7.0901

>> myLogSum([30 20], 40)
Error using myLogSum (line 12)
The value of 'b' is invalid. Expected input to be of size 1x2 when it is
actually size 1x1.

>> myLogSum([30 20], [40 1])

ans =

    7.0901    2.9957

>> myLogSum([30 20], [40 -1])
Error using myLogSum (line 12)
The value of 'b' is invalid. Expected input to be an array with all of the
values > 0.

答案 1 :(得分:1)

从 Matlab 2019b 开始,我建议使用 arguments validation block

https://de.mathworks.com/help/matlab/ref/arguments.html?searchHighlight=arguments&s_tid=srchtitle

它仍然有一些局限性,但总体来说还是相当通用的。它迫使验证具有一定的一致性。

% My function
function result = myLogSum(a,b)

% Arguments validation block
arguments
    a;
    b {mustBeEqualSize(a,b)};
end

% Calculate the log sum
result = log(a) + log(b);

end

function mustBeEqualSize(a,b)
% Test for equal size
if ~isequal(size(a),size(b))
    eid = 'mustBeEqualSize:sizesNotEqual';
    msg = 'Size of first input must equal size of second input.';
    throwAsCaller(MException(eid,msg))
end
end