hi,
I want to use a while loop on matrices, to define a new matrix by calculating one row each time.
I'm trying to do it without creating another loop that will go over the columns. Is that possible?
for example:
z5 and k5 are known matrices. This loop defines c5.
i=1;
while i<imax
if z5(i,:) < z5(i-1,:)
c5(i,:) = k5(i,:);
elseif z5(i,:) > z5(i-1,:)
c5(i,:) = z5(i,:);
else
c5(i,:) = c5(i-1,:);
end
i=i+1;
end
It's not doing what I want it to do and I'm not sure what exactly its doing.
Would appreciate any help and clarification on this matter.

10 comentarios

Torsten
Torsten el 26 de Jul. de 2019
result = z5(i,:) < z5(i-1,:)
is not the same as
for j=1:size(z5,2)
result(j) = z5(i,j) < z5(i-1,j)
end
Test it and see the difference.
Galgool
Galgool el 26 de Jul. de 2019
I know, but I dont want to create anothor loop (on the rows) as you did.
Is there a way?
Bob Thompson
Bob Thompson el 26 de Jul. de 2019
Editada: Bob Thompson el 26 de Jul. de 2019
if z5(i,:) < z5(i-1,:)
How is this evaluated for each row?
A = [1 2 3;
4 2 1];
It could be argued that the second row of A is greater than the first, because the sum total of the elements is greater than the first row. It could also be argued that the second row is not greater because each individual element is not greater than the corresponding element in the first row.
An inequality comparison statement is really only useful for comparing one piece of information with another. If you would like to complete all of these comparisons at once, and don't want to use a loop, you can use & to have multiple comparisons for one if statement, but this is very tedious for a large z5 matrix.
if z5(i,1) < z5(i-1,1) & z5(i,2) < z5(i-1,2)
Galgool
Galgool el 26 de Jul. de 2019
Editada: Galgool el 26 de Jul. de 2019
No, I dont want to complete all of these comparisons at once.
What I actually want is for each element in the matrices to apply the conditions.
I mean that for any row - j :
i=1;
while i<imax
if z5(i,j) < z5(i-1,j)
c5(i,j) = k5(i,j);
elseif z5(i,j) > z5(i-1,j)
c5(i,j) = z5(i,j);
else
c5(i,j) = c5(i-1,j);
end
i=i+1;
end
But I want to do this without looping on j, and thought that using ":" will replace the j looping.
Is this possible in any other way than looping?
Torsten
Torsten el 26 de Jul. de 2019
As you can see from our answers, it's not possible without looping because comparisons must be done elementwise to get the results you expect to get.
Galgool
Galgool el 26 de Jul. de 2019
actually I've just tested it and you're 100% wrong.
As:
i=2;
while i<imax+1
ab1(i,:) = z5(i,:) < z5(i-1,:);
i=i+1;
end
ab1 gives a matrix identical to:
j=1;
while j<jmax+1
i=2;
while i<imax+1
ab1(i,j) = z5(i,j) < z5(i-1,j);
i=i+1;
end
j=j+1;
end
But for some reason c5 doesnt define properly...
Torsten
Torsten el 26 de Jul. de 2019
Editada: Torsten el 26 de Jul. de 2019
If you test
if z5(i,:) < z5(i-1,:)
the result will be true only if the vector v = z5(i,:) < z5(i-1,:) is a vector of ones at all positions.
So if there is only one case for which z5(i,j) >= z5(i-1,j), all other cases for which z5(i,:) < z5(i-1,:) are ignored, positions for which you intend to set c5(i,:) = k5(i,:), I guess.
Maybe this is what you want to do:
jdx1 = z5(i,:) < z5(i-1,:);
jdx2 = z5(i,:) > z5(i-1,:);
jdx3 = z5(i,:) == z5(i-1,:);
c5(i,jdx1) = k5(i,jdx1);
c5(i,jdx2) = z5(i,jdx2);
c5(i,jdx3) = c5(i-1,jdx3);
Galgool
Galgool el 26 de Jul. de 2019
Actually you're worng. ab1(i,:) = z5(i,:) < z5(i-1,:); works properly (as you can see in (37,8)):
z5:
z5.JPG
ab1:
ab1.JPG
Torsten
Torsten el 26 de Jul. de 2019
Editada: Torsten el 26 de Jul. de 2019
I'm talking about the "if z5(i,:) < z5(i-1,:) ", not about the "v = z5(i,:) < z5(i-1,:) "
Read my answer carefully.
the cyclist
the cyclist el 26 de Jul. de 2019
Editada: the cyclist el 26 de Jul. de 2019
To reiterate what Torsten is saying ...
To enter an if statement on a vector condition, all elements of that vector have to evaluate to true. MATLAB doesn't discern the if condition element-by-element.
That is the fatal flaw in your algorithm

Iniciar sesión para comentar.

 Respuesta aceptada

Guillaume
Guillaume el 26 de Jul. de 2019

0 votos

@galgool, before calling someone wrong please learn the language properly, in particular how if works when given a vector as an expression. From the doc:
An expression is true when its result is nonempty and contains only nonzero elements (logical or real numeric). Otherwise, the expression is false.
So, let's look at
if z5(i,:) < z5(i-1,:)
The expression is
z5(i,:) < z5(i-1,:)
The result of that expression is a logical vector (array of 0s and 1s). As per the rule above, the if is true only if all the elements of the vector are 1. I.e. the only time the expression is true is when z5(i, j) < z5(i-1, j) for all j. In general, you should avoid passing a vector to if because people don't know the rule above. The expression you've written is exactly equivalent to:
if all(z(5(i,;) < z5(i-1,:))
which is clearer.
As others have said, you will also have to loop over the columns.
Note that:
i = 2; %your code would error if you actually started at 1!
while i < constant
%some code that doesn't change i or the constant
i = i+1;
end
is more simply written as a for loop:
for i = 2:constant
%some code that doesn't change i or the constant
end
Note that if you didn't have the dependence on the previous c5 row, when z5(i,j) == z5(i-1, j), the whole thing could written without any loop at all.

4 comentarios

Galgool
Galgool el 28 de Jul. de 2019
Thanks for putting me staright and explaining the details.
instead of using:
if z5(i,j) < z5(i-1,j)
c5(i,j) = k5(i,j);
elseif z5(i,j) > z5(i-1,j)
c5(i,j) = z5(i,j);
else
c5(i,j) = c5(i-1,j);
end
I've now written the whole thing without if:
c5(i,:) = k5(i,:).*(z5(i,:) < z5(i-1,:)) + z5(i,:).*(z5(i,:) > z5(i-1,:)) + c5(i-1,:).*(z5(i,:) == z5(i-1,:));
It works properly
Guillaume
Guillaume el 29 de Jul. de 2019
That's fine as long as you write a comment explaining exactly what this line does.
My preference, rather than multiplying by logical vectors to select the actual working part of the expression would be:
c5(i, z5(i, :) < z5(i-1, :)) = k5(i, z5(i, :) < z5(i-1, :));
c5(i, z5(i, :) > z5(i-1, :)) = z5(i, z5(i, :) > z5(i-1, :));
c5(i, z5(i, :) == z5(i-1, :)) = c5(i-1, z5(i, :) == z5(i-1, :));
More lines but a lot easier to understand
Galgool
Galgool el 29 de Jul. de 2019
Its difficult for me to understand the lines you wrote, as you put the inequality condition within the columns of c5, k5 and z5. doesnt that just give zeros and ones for the columns index?
And another thing - is it possible to get it done without a loop? the only eason I used a loop is because c5(i) is dependent on c5(i-1), z5(i-1) and k5(i-1)...
Guillaume
Guillaume el 29 de Jul. de 2019
Maybe, this is clearer this way:
mask = z5(i, :) < z5(i-1, :); c5(i, mask) = k5(i, mask); %set c5 values for which mask is true to matching k5 values
mask = z5(i, :) > z5(i-1, :); c5(i, mask) = z5(i, mask); %set c5 values for which mask is true to matching z5 values
mask = z5(i, :) == z5(i-1, :); c5(i, mask) = c5(i-1, mask); %set c5 values for which mask is true to matching value on previous row
If there was the dependence on the previous row of c5, this could be done trivially without a loop, but unfortunately with that dependence it does need the loop... unless you are guaranteed not to have two consecutive identical value in any z5 column.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Loops and Conditional Statements en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 26 de Jul. de 2019

Comentada:

el 29 de Jul. de 2019

Community Treasure Hunt

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

Start Hunting!

Translated by