Generalizing an IF and FPRINTF expression

조회 수: 1 (최근 30일)
Marcelin Dierickx
Marcelin Dierickx 2019년 1월 15일
댓글: Marcelin Dierickx 2019년 1월 16일
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