A compact way to replace zeros with Inf in a matrix

Would you be so nice to suggest me a more compact way to replace zeros with Inf in the following matrix? (maybe with just one line of code?)
% Input
A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
% Replace zeros with Inf
[row,col] = ind2sub(size(A),find(A==0));
for i = 1 : length(row)
A(row(i),col(i))=Inf;
end
% Output
A
A = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9

 Respuesta aceptada

J. Alex Lee
J. Alex Lee el 16 de Oct. de 2023
Editada: J. Alex Lee el 16 de Oct. de 2023
You can implicitly index "linearly" for any arrays - it will do all the ind2sub and sub2ind in the background:
% Input
A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
B = A;
% Replace zeros with Inf
[row,col] = ind2sub(size(A),find(A==0));
for i = 1 : 3
A(row(i),col(i))=Inf;
end
% Output
A
A = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9
B(B==0) = Inf
B = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9
isequal(A,B)
ans = logical
1

Más respuestas (4)

Les Beckham
Les Beckham el 16 de Oct. de 2023
Editada: Les Beckham el 16 de Oct. de 2023
If you want to retain the non-zero elements of A and replace the zeros with Inf, then this is how I would suggest that you do that.
% Input
A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
A(A==0) = Inf
A = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9
Note that your loop doesn't do this, it creates a matrix with Inf in the positions of the zeros in A and zero everywhere else. If that is really what you want then you could do that like this.
A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
B = zeros(size(A));
B(A==0) = Inf
B = 5×5
Inf 0 0 0 0 0 0 0 0 0 0 Inf 0 0 0 0 0 0 0 Inf 0 0 0 0 0

3 comentarios

Sim
Sim el 16 de Oct. de 2023
Editada: Sim el 16 de Oct. de 2023
Thanks @Les Beckham :-) You and @J. Alex Lee gave me the same solution, i.e.
B(B==0) = Inf
Therefore, many thanks to both of you!
Les Beckham
Les Beckham el 16 de Oct. de 2023
Editada: Les Beckham el 16 de Oct. de 2023
You are quite welcome.
If you are just getting started with Matlab, I would highly recommend that you take a couple of hours to go through the free online tutorial: Matlab Onramp
Sim
Sim el 17 de Oct. de 2023
thanks :-)

Iniciar sesión para comentar.

Allso just for fun.
A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
A=A+1./(A~=0)-1
A = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9

2 comentarios

Alexander
Alexander el 16 de Oct. de 2023
It can't be shorter. Thumbs up.
Sim
Sim el 17 de Oct. de 2023
Thumb up! :-)

Iniciar sesión para comentar.

A = [0 3 2 5 6;
1 1 4 3 2;
9 0 8 1 1;
5 9 8 2 0;
3 1 7 6 9];
A(~A) = inf
A = 5×5
Inf 3 2 5 6 1 1 4 3 2 9 Inf 8 1 1 5 9 8 2 Inf 3 1 7 6 9

2 comentarios

by the way, on huge matrices this is actually faster than testing for zero.
Sim
Sim el 23 de Oct. de 2023
Editada: Sim el 23 de Oct. de 2023
@Walter Roberson Wow!! Thumb up! :-)

Iniciar sesión para comentar.

Alexander
Alexander el 16 de Oct. de 2023
Only for fun. My maybe a bit old-fashoned approach would be:
B=1./A;
B(B==Inf)=0;
C=1./B

6 comentarios

This will result into precision errors. Introducing extra operations just seems to complicate the process.
Sim
Sim el 17 de Oct. de 2023
Nice :-)
Alexander
Alexander el 17 de Oct. de 2023
@Joshi, I checked this with very large (^100) and very small numbers (^-100), but "format long" shows the same result. Maybe there is a loss of precision a 100 digits (after the dot) later, but this is more an academic issue than an engineering one (IMHO). But Matt's solution and mine is about much much faster than the accepted solution.
Stephen23
Stephen23 el 17 de Oct. de 2023
Editada: Stephen23 el 17 de Oct. de 2023
As Dyuman Joshi correctly wrote, there definitely are precision issues.
"but "format long" shows the same result"
FORMAT LONG does not have sufficient precision to demonstrate that two values are exactly equal.
"Maybe there is a loss of precision a 100 digits (after the dot) later, but this is more an academic issue than an engineering one (IMHO)"
And yet when we test your method it fails for fairly small integers, showing that it is not just an "academic issue" but a real "engineering" issue caused by not really understanding the behaviors of binary floating point numbers. Anyone who has spent time on this forum (or any other computing forum) will know that floating point precision is much more than just an "academic issue".
Anyway, lets try it right now with a random value I just picked:
format long G
A = 49; % also 93, 98, 99, 103, 105, 107, 117, 123, 186, etc...
B=1./A;
B(B==Inf)=0;
C=1./B % oh no, the alignment is already a warning:
C =
49
D = A;
D(D==0) = Inf % the simple, clear, correct, robust approach.
D =
49
isequal(C,D) % oh no, not the same outputs!!!
ans = logical
0
fprintf('%.999g\n',C,D) % yep, your approach has significant precision issues.
49.00000000000000710542735760100185871124267578125 49
Alexander
Alexander el 22 de Oct. de 2023
Thanks @Stephen23 for the advice and yes, there are precision errors. But I think it depends on the problem you have to solve whether these are significant or not.
Stephen23
Stephen23 el 23 de Oct. de 2023
"But I think it depends on the problem you have to solve whether these are significant or not."
I can't think of many problems where a more complex, slower, obfuscated approach with precision errors would be preferred over the simpler, clearer, much more robust approach using indexing. Can you give an example?

Iniciar sesión para comentar.

Categorías

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

Preguntada:

Sim
el 16 de Oct. de 2023

Editada:

Sim
el 23 de Oct. de 2023

Community Treasure Hunt

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

Start Hunting!

Translated by