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
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?
Marcelin Dierickx
Marcelin Dierickx 2019-1-16
编辑:Marcelin Dierickx 2019-1-16
Hello,
Thank you for commenting.
You're right, the "any" is well supposed to be written so. I faced it some hours ago upon trying my code.
Your code is good but not what I want. My point is to write only one "fprintf".
A and B are volumic masses of respectively the atmosphere and a solid that is in that atmosphere. 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. One of them can be a vector, but not both at the same time, so that I can plot the result of the global code as a function of A, B or another variable. I could make both a vector and make a 3D plot but It'd be less clear to me.
The return are necessary, there is no purpose in calculating the rest of the code (whihc is ~150 lines, I won't ask you to read it all) if B is lighter than A.
Thank you again :-)

请先登录,再进行评论。

采纳的回答

Rik
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.
  2 个评论
Marcelin Dierickx
Marcelin Dierickx 2019-1-16
Hello,
Yes I had failed my "any" !
Thank you for your answer, I'll try your suggestions right now.
Coming back if it works :-)
Marcelin Dierickx
Marcelin Dierickx 2019-1-16
Works perfectly !! Thank you very much !
I didnt know the trick with A(...,min(...,end)) which returns 1 if it exceeds. Exactly what i needed.
I finally wrote it so:
if any(B<=A)
fprintf('B > %g or A < %g\n\n',A(1,min(find(B<=A,1,'last'),end)),B(1,min(find(B<=A,1,'first'),end)))
return
end
Thank you again !

请先登录,再进行评论。

更多回答(1 个)

Guillaume
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 CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

标签

产品


版本

R2016b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by