Clear Filters
Clear Filters

How to stop unwanted rows being added when constructing a matrix in a for loop

41 views (last 30 days)
Hi there,
just a simple question I think.
I am trying to construct a matrix in a quick way using a for loop. Because the values for diagonals are the same I can using indexing like (i,i) and (i+1,i) etc. However, apart from the first diagonal I input (i,i), the second diagonal (i,i+1) adds an extra row and column to my original matrix.
Here is my code:
clear, clc, close all
mat = zeros(7,7)
n = size(mat,1)
for i = 1:n
mat(i,i) = 6
mat(i,i+1) = -4
end
If you run the code, the diagonal containing -4 adds on a extra row and column at the end; making a 7x7 matrix to an 8x8. This is very frustraing and I do not want this!
Can I ask what its the trick to getting around this, please?
Many thanks
Scott
  1 Comment
Stephen23
Stephen23 on 5 Sep 2024 at 23:09
n = 7;
toeplitz([6,zeros(1,n-1)],[6,-4,zeros(1,n-2)])
ans = 7x7
6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 5 Sep 2024 at 19:04
The reason is that there are the same number of ‘6’ and ‘-4’ being created in the loop. There needs to be one less ‘-4’.
clear, clc, close all
mat = zeros(7,7);
n = size(mat,1);
for i = 1:n
mat(i,i) = 6;
mat(i,i+1) = -4;
end
mat
mat = 7x8
6 -4 0 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 0 6 -4
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
N = 7;
mat2 = diag(ones(1,N)*6); % Use 'diag'
mat2 = + mat2 + diag(ones(1,N-1)*-4, 1)
mat2 = 7x7
6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
One way to get around that iis to use the diag function to creeate the matrix.
.

More Answers (3)

ScottB
ScottB on 5 Sep 2024 at 18:57
mat = zeros(7,7)
n = size(mat,1)
for i = 1:n
mat(i,i) = 6
if i ==7
else
mat(i,i+1) = -4
end
end
mat =
6 -4 0 0 0 0 0
0 6 -4 0 0 0 0
0 0 6 -4 0 0 0
0 0 0 6 -4 0 0
0 0 0 0 6 -4 0
0 0 0 0 0 6 -4
0 0 0 0 0 0 6
  1 Comment
Voss
Voss on 5 Sep 2024 at 19:05
Or
mat = zeros(7,7);
n = size(mat,1);
for i = 1:n
mat(i,i) = 6;
if i ~= n
mat(i,i+1) = -4;
end
end
mat
mat = 7x7
6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Sign in to comment.


Steven Lord
Steven Lord on 5 Sep 2024 at 19:12
Since you're creating matrices with diagonal bands, consider using the diag or spdiags functions.
n = 7;
mainDiagonal = diag(6*ones(n, 1))
mainDiagonal = 7x7
6 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
upperDiagonal = diag(-4*ones(n-1, 1), 1)
upperDiagonal = 7x7
0 -4 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
A = mainDiagonal + upperDiagonal
A = 7x7
6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Note that when I created upperDiagonal I used a vector of all -4 values that had length one shorter than the vector of 6 values I used to create mainDiagonal. This made it so upperDiagonal was n-by-n rather than (n+1)-by-(n+1) as it would have been had I used -4*ones(n, 1).
B = diag(-4*ones(n, 1), 1)
B = 8x8
0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0 -4 0 0 0 0 0 0 0 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
For bands below the diagonal, use a negative value as the second input.
lowerDiagonal = diag(-8*ones(n-1, 1), -1)
lowerDiagonal = 7x7
0 0 0 0 0 0 0 -8 0 0 0 0 0 0 0 -8 0 0 0 0 0 0 0 -8 0 0 0 0 0 0 0 -8 0 0 0 0 0 0 0 -8 0 0 0 0 0 0 0 -8 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
Here are the numbers for which band contains each element of the matrix.
bandNumbers = toeplitz(0:-1:-(n-1), 0:(n-1))
bandNumbers = 7x7
0 1 2 3 4 5 6 -1 0 1 2 3 4 5 -2 -1 0 1 2 3 4 -3 -2 -1 0 1 2 3 -4 -3 -2 -1 0 1 2 -5 -4 -3 -2 -1 0 1 -6 -5 -4 -3 -2 -1 0
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
For spdiags you don't have to create each band individually, though the syntax is a little bit more complicated. The command below puts 6 on the 0 (main) diagonal of S and -4 on the +1 (upper) diagonal, and makes S an n-by-n matrix.
S = spdiags([6 -4], [0 1], n, n)
S =
(1,1) 6 (1,2) -4 (2,2) 6 (2,3) -4 (3,3) 6 (3,4) -4 (4,4) 6 (4,5) -4 (5,5) 6 (5,6) -4 (6,6) 6 (6,7) -4 (7,7) 6
Since S is sparse it's displayed slightly differently. Convert it to full and it looks like A above.
F = full(S)
F = 7x7
6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6 -4 0 0 0 0 0 0 6
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>

Scott Banks
Scott Banks on 5 Sep 2024 at 22:18
Briiliant, thanks guys for all youre help!

Categories

Find more on Data Type Identification in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!