Matrix 'if' statement

198 vues (au cours des 30 derniers jours)
Eva Carrillo
Eva Carrillo le 2 Déc 2019
Modifié(e) : Manuel Dullnig le 31 Août 2021
I just learned how to do matrices today, and am quite confused on this problem. So I have to create a 100 x 100 matrix. Every spot in the matrix takes on the value , where i represents the row and j represents the column location. I have a formula in which the value K is defined as the greater value of i and j. I need to create an if loop that compares the row and column position values and chooses the larger of the two, then defines that as the variable K.
I don't know what kind of syntax to use in terms of matrices. I know how to build an if staement, but am jsut simply confused on the kind of matlab syntax that needs to be followed.
  2 commentaires
KALYAN ACHARJYA
KALYAN ACHARJYA le 2 Déc 2019
Modifié(e) : KALYAN ACHARJYA le 2 Déc 2019
%create matrics
[r c]=size(matrix); % find row and col number, If not known already
for i=1:r
for j=1:c
if condition
matrix(i,j)=...
end
end
end
You can do same without loop also. Being as beginer atleast you should learn how to use loop to do iteration on 1D or 2D array
Welcome to Matlab World! Please try and try, you can. We are here to help you!
Happy Learning & Good Luck!
:)
Manuel Dullnig
Manuel Dullnig le 24 Août 2021
KALYAN you said one can do it without a loop. I need to do this without the loop, can you show me how?

Connectez-vous pour commenter.

Réponses (2)

John D'Errico
John D'Errico le 24 Août 2021
Modifié(e) : John D'Errico le 24 Août 2021
One thing that new users of MATLAB mistake, is they want an if statement to apply to every element of a matrix or vector. For example:
M = magic(7)
M = 7×7
30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37 5 14 16 25 34 36 45 13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
So M is a matrix. Now users want to have an if statement that will do something different for every element of the matrix, depending on some test, and MATLAB does not have such an ability, at least not as they want. But there are some things you can do. For example, suppose I wanted to divide all of the even numbers by 2, but for the odd numbers, I want to multiply by 3, and then add 1? (You may recognize what I am doing here, if not, then you could do some reading about the Collatz conjecture, sometimes just called the 3n+1 problem.)
Solution 1: Just use a loop.
for i = 1:numel(M)
if rem(M(i),2) == 0
M(i) = M(i)/2; % even condition
else
M(i) = 3*M(i) + 1; % odd condition
end
end
M
M = 7×7
15 118 24 4 5 58 14 19 142 22 28 9 82 88 23 3 4 52 13 106 112 16 7 8 76 17 18 136 40 46 12 100 21 22 2 64 70 16 124 130 10 6 11 94 20 148 1 34 10
So it did exactly as we need it to do, operating on each element of M separately. Note that the loop uses a linear index, treating the matrix as if it were a vector of elements. This works in MATLAB, so I did not need to create a double loop on the rows AND the columns of M.
But the MATLAB way is to use matrices. That is how MATLAB is really written to be efficient. So we might have used this next idea. (I'll just apply it directly to the last result of M.)
Solution 2:
% create a boolean variable that is either 0 or 1, depending on whether the
% corresponding element in M was even or odd.
evenloc = rem(M,2) == 0;
oddloc = ~evenloc;
M(evenloc) = M(evenloc)/2;
M(oddloc) = 3*M(oddloc) + 1;
M
M = 7×7
46 59 12 2 16 29 7 58 71 11 14 28 41 44 70 10 2 26 40 53 56 8 22 4 38 52 9 68 20 23 6 50 64 11 1 32 35 8 62 65 5 3 34 47 10 74 4 17 5
As you can see, this also worked. No explicit loops were used, although internally inside the guts of MATLAB, it will be performing a loop in a lower level language, so an implicit loop. It employed what is called a boolean index. I could also have used find in a very similar way.
Solution 3:
% create a list of the elements in M that were even,
% and another list of the odd elements.
evenloc = find(rem(M,2) == 0);
oddloc = find(rem(M,2) == 1);
% Use those lists to index into M.
M(evenloc) = M(evenloc)/2;
M(oddloc) = 3*M(oddloc) + 1;
M
M = 7×7
23 178 6 1 8 88 22 29 214 34 7 14 124 22 35 5 1 13 20 160 28 4 11 2 19 26 28 34 10 70 3 25 32 34 4 16 106 4 31 196 16 10 17 142 5 37 2 52 16
These are the common solutions you may see. Certainly there are others ways to do it too. I might have tried to be tricky, perhaps like this:
Solution 4:
mfac = [1/2 3];
afac = [0 1];
M = mfac(rem(M,2) + 1) .* M + afac(rem(M,2) + 1)
M = 7×7
70 89 3 4 4 44 11 88 107 17 22 7 62 11 106 16 4 40 10 80 14 2 34 1 58 13 14 17 5 35 10 76 16 17 2 8 53 2 94 98 8 5 52 71 16 112 1 26 8
You may wish to look carefully at this last one. Why did it work? (Because it does work.) We could even use the last idea to usein a simple iteration scheme to play with the classic Collatz problem.
mfac = [1/2 3];
afac = [0 1];
% creating a simple function handle to perform one step of the Collatz
% iteration.
Miter = @(M) mfac(rem(M,2) + 1) .* M + afac(rem(M,2) + 1);
niter = 0;
while any(~ismember(M(:),[1 2 4]))
niter = niter + 1;
M = Miter(M);
end
niter
niter = 105
% and so, after 105 more iterations, we see that every element has now
% stabilized into the 3 oscillating terminal elements in the famous
% Collatz conjecture.
M
M = 7×7
4 1 2 4 4 2 4 4 2 1 1 2 4 4 1 2 4 4 1 1 4 2 2 1 2 1 4 1 4 2 1 2 2 1 2 1 4 2 1 2 1 4 4 1 2 4 1 2 1
And there are cetainly other creative ways to solve the problem. In any such scheme I should have probably worried if the number was too large to be exactly representable as an integer in floating point arithematic in MATLAB, thus as a double. The limit for that is calling flintmax in MATLAB, but now I am digressing too far.
  3 commentaires
Jan
Jan le 30 Août 2021
Modifié(e) : Jan le 30 Août 2021
@Manuel Schiestl: A simpler version:
x = (1:10).'; % No need to create the full matrices
y = 1:10;
z = cos(0.1 * x .* y .^ 2); % Implicit expanding, Matlab >= R2016b
z((x>5) & (y>5)) = 5
z = 10×10
0.9950 0.9211 0.6216 -0.0292 -0.8011 -0.8968 0.1865 0.9932 -0.2435 -0.8391 0.9801 0.6967 -0.2272 -0.9983 0.2837 0.6084 -0.9304 0.9728 -0.8814 0.4081 0.9553 0.3624 -0.9041 0.0875 0.3466 -0.1943 -0.5336 0.9392 0.6729 0.1543 0.9211 -0.0292 -0.8968 0.9932 -0.8391 -0.2598 0.7314 0.8928 0.5536 -0.6669 0.8776 -0.4161 -0.2108 -0.1455 0.9978 0.6603 0.8064 0.8342 -0.9425 0.9650 0.8253 -0.7374 0.6347 -0.9847 -0.7597 5.0000 5.0000 5.0000 5.0000 5.0000 0.7648 -0.9422 0.9999 0.2030 0.2194 5.0000 5.0000 5.0000 5.0000 5.0000 0.6967 -0.9983 0.6084 0.9728 0.4081 5.0000 5.0000 5.0000 5.0000 5.0000 0.6216 -0.8968 -0.2435 -0.2598 -0.8733 5.0000 5.0000 5.0000 5.0000 5.0000 0.5403 -0.6536 -0.9111 -0.9577 0.9912 5.0000 5.0000 5.0000 5.0000 5.0000
There is no need to compare a logical with 1:
oddloc = (lrx==1 & lry==1);
% Simpler:
oddloc = (lrx & lry)
Manuel Dullnig
Manuel Dullnig le 31 Août 2021
thank you so much for taking the time!

Connectez-vous pour commenter.


Wan Ji
Wan Ji le 24 Août 2021
If you do not want the loop, then
M = 100; N = 100;
[j, i] = meshgrid(1:N,1:M);
q = i>j;
A(q) = i(q);
A(~q)=j(~q);
  2 commentaires
Jan
Jan le 24 Août 2021
|meshgrid| creates matrices, but for the comparison it is cheaper to work with vectors:
col = (1:N).';
row = (1:M);
q = row > col; % Auto-expand working for >= R2016b
Wan Ji
Wan Ji le 24 Août 2021
Hi, Jan
Thank you very much for your comment.
You open a door of new world in matlab for me. How surprising to see its simple and beautiful.
Wan Ji

Connectez-vous pour commenter.

Catégories

En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by