Generalizing an IF and FPRINTF expression
2 次查看(过去 30 天)
显示 更早的评论
Hello,
I got a part of code looking like this:
A = ... % can be a scalar or a vector
B = ... % can be a scalar or a vector if A is scalar
if any(B-A) <= 0 && length(B-A) == length(B)
fprintf('B > %g or A < %g',A,B(1,find(B-A<=0,1)))
return
elseif any(B-A) <= 0 && length(B-A) == length(A)
fprintf('B > %g or A < %g',A(1,find(B-A<=0,1)),B)
return
end
A and B can't both be vectors at the same time. They can both be scalars at the same time
Is there a way to have only one FPRINTF ?
It would need the code not to acces out of (1,1) for the scalar variable.
It's to have less lines in the final code. I would use it elsewhere too. It may be a bit perfectionism but would be usefull.
Thank you in advance for answering.
EDIT: actually the question is "How to return 1 if the index exceeds matrix dimensions" ?
2 个评论
Guillaume
2019-1-15
I suspect that your
any(B-A) <= 0
is supposed to be
any(B-A <= 0)
Otherwise, it doesn't make much sense.
I don't really understand what you're trying to achieve but in any case, code clarity should trump succinctness. What your code is mising is a comment that explains what it is doing. Personally, I would have written your current code as:
if any(B - A <= 0)
if numel(B) > 1
fprintf('B > %g or A < %g',A,B(1,find(B-A<=0,1)))
elseif numel(A) > 1
fprintf('B > %g or A < %g',A(1,find(B-A<=0,1)),B)
end
end
Even longer but clearer, and avoids doing the same any test twice.
Are the return actually necessary?
采纳的回答
Rik
2019-1-15
Since your actual question is much easier to understand, I'll try to answer that one. Below you will find two strategies that ensure you will either get a specific index, or index 1. I removed some of the logic you had, and I also edited the find in the second strategy.
I would also urge you to have a look at the doc for any, as any(B-A) <= 0 is equivalent to ~any(B-A)
%example A and B
A=4;
B=[5 2 1 9];
ind_A=find(B-A<=0,1);
ind_B=find(B-A<=0,1);
if ind_A>size(A,2),ind_A=1;end
if ind_B>size(B,2),ind_B=1;end
fprintf('B > %g or A < %g\n',A(1,ind_A),B(1,ind_B))
%or:
ind=find(B<=A,1);%ind=find(B-A<=0,1);
fprintf('B > %g or A < %g\n',...
A(1,min(ind,end)),B(1,min(ind,end)))
The trick in the second one is that within an indexing context, the end keyword will also work in another function call.
更多回答(1 个)
Guillaume
2019-1-16
The code checks if B is greater than A so that the solid will sink in the atmosphere, it's to ensure that I didn't give wrong values to A and B.
Then, in my opinion, you're taking the wrong approach. I would make the code errors if the inputs do not satisfy the preconditions required by it. The best way to do that is, at the beginning of the function, to use validateattributes and/or assert
validateattributes(A, {'numeric'}, {'vector', 'finite'}); %scalar pass the vector check
validateattributes(B, {'numeric'}, {'vector', 'finite'});
assert(isscalar(A) || isscalar(B), 'One of A or B must be scalar');
assert(all(B > A), 'B must be greater than A');
This is much clearer than your accepted answer. It self-documents the preconditions of your code and the user gets a descriptive error message telling them what the problem is.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Matrix Indexing 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!