for loop does not iterate

3 ビュー (過去 30 日間)
Konrad Suchodolski
Konrad Suchodolski 2023 年 11 月 21 日
コメント済み: Voss 2023 年 11 月 21 日
I am trying to get used to matlab, but I am stuck.
I'm not able to iterate through my x_roots and separate real roots form complex ones
This is my code:
clear all
close all
syms n
w = @(x) 0.01.*x.^4-0.04.*x.^3+0.02.*x.^2+0.04.*x-0.03;
w_vec = [0.01 0.04 0.02 0.04 0.03];
x = -2:.2:4;
w_y = w(x);
x_roots = roots(w_vec)
x_roots =
-3.6921 + 0.0000i 0.2003 + 1.0521i 0.2003 - 1.0521i -0.7084 + 0.0000i
x_realroots = [];
for i=x_roots
~round(imag(i))
if (~round(imag(i)))
round(imag(i))
x_realroots = [x_realroots i];
else
continue;
end
end
ans = 4×1 logical array
1 0 0 1
x_realroots
x_realroots = []
So yeah, I just wanted to get real roots, but now I'm learning basic matlab.
Please explain to me why i cannot iterate through x_roots.

採用された回答

Voss
Voss 2023 年 11 月 21 日
編集済み: Voss 2023 年 11 月 21 日
"Please explain to me why i cannot iterate through x_roots."
A for loop in MATLAB iterates over the columns of what you give it. Here are some simple examples to illustrate what I mean:
Example 1: row vector
x = 1:3 % a row vector with 3 elements (i.e., 3 columns)
x = 1×3
1 2 3
count = 0;
for ii = x % for loop iterates 3 times
count = count+1;
disp("Iteration: " + count)
disp("ii = ")
disp(ii) % ii is a column of x each time (each column of x is a single element)
end
Iteration: 1
ii =
1
Iteration: 2
ii =
2
Iteration: 3
ii =
3
Example 2: matrix:
x = magic(3) % a matrix with 3 columns
x = 3×3
8 1 6 3 5 7 4 9 2
count = 0;
for ii = x % for loop iterates 3 times
count = count+1;
disp("Iteration: " + count)
disp("ii = ")
disp(ii) % ii is a column of x each time
end
Iteration: 1
ii =
8 3 4
Iteration: 2
ii =
1 5 9
Iteration: 3
ii =
6 7 2
Example 3: column vector:
x = [1;2;3] % a column vector with 3 elements
x = 3×1
1 2 3
count = 0;
for ii = x % for loop iterates 1 time (x has only one column)
count = count+1;
disp("Iteration: " + count)
disp("ii = ")
disp(ii) % ii is the entirety of x
end
Iteration: 1
ii =
1 2 3
In your code your variable x_roots is a column vector, so your for loop iterates one time, and in that iteration i is equal to x_roots.
clear all
close all
syms n
w = @(x) 0.01.*x.^4-0.04.*x.^3+0.02.*x.^2+0.04.*x-0.03;
w_vec = [0.01 0.04 0.02 0.04 0.03]
w_vec = 1×5
0.0100 0.0400 0.0200 0.0400 0.0300
x = -2:.2:4;
w_y = w(x);
x_roots = roots(w_vec) % x_roots is a column vector ...
x_roots =
-3.6921 + 0.0000i 0.2003 + 1.0521i 0.2003 - 1.0521i -0.7084 + 0.0000i
count = 0;
for i=x_roots % ... so the for loop iterates once
count = count+1;
disp("Iteration: " + count)
disp("i = ")
disp(i)
end
Iteration: 1
i =
-3.6921 + 0.0000i 0.2003 + 1.0521i 0.2003 - 1.0521i -0.7084 + 0.0000i
But you want to iterate over each element of x_roots, not over each column of x_roots. An easy way to do that is to tranpose x_roots in the for expression so that what the for sees is a row vector, in which case it iterates once for each element:
x_realroots = [];
for i=x_roots.' % x_roots.' is a row vector, so the loop iterates multiple times
~round(imag(i))
if (~round(imag(i)))
round(imag(i))
x_realroots = [x_realroots i];
else
continue;
end
end
ans = logical
1
ans = 0
ans = logical
0
ans = logical
0
ans = logical
1
ans = 0
x_realroots
x_realroots = 1×2
-3.6921 -0.7084
A more general solution, which would work whether x_roots is a row vector or a column vector (or indeed an array of any size or dimensionality), would be, again in the for expression, convert x_roots into a column vector using (:) notation and then transpose to produce a row vector of all the elements of x_roots:
for i = x_roots(:).' % iterates over the elements of x_roots, regardless of its size
% ...
end
  2 件のコメント
Konrad Suchodolski
Konrad Suchodolski 2023 年 11 月 21 日
Thank you very much :D
Voss
Voss 2023 年 11 月 21 日
You're welcome!

サインインしてコメントする。

その他の回答 (2 件)

madhan ravi
madhan ravi 2023 年 11 月 21 日
編集済み: madhan ravi 2023 年 11 月 21 日
x_realroots = x_roots(abs(imag(x_roots)) < 1e-4) % 1e-4 tolerance

Les Beckham
Les Beckham 2023 年 11 月 21 日
Array indices in Matlab must be positive integers (or logical). You are trying to us xroots, a vector of complex numbers as the index in your for loop. Loop using integers instead and use that index to select each element of x_roots.
clear all
close all
syms n
w = @(x) 0.01.*x.^4-0.04.*x.^3+0.02.*x.^2+0.04.*x-0.03;
w_vec = [0.01 0.04 0.02 0.04 0.03];
x = -2:.2:4;
w_y = w(x);
x_roots = roots(w_vec)
x_roots =
-3.6921 + 0.0000i 0.2003 + 1.0521i 0.2003 - 1.0521i -0.7084 + 0.0000i
x_realroots = [];
% for i=x_roots
for i = 1:numel(x_roots)
% ~round(imag(i))
% if (~round(imag(i)))
if (imag(x_roots(i)) == 0)
% round(imag(i))
% x_realroots = [x_realroots i];
x_realroots = [x_realroots real(x_roots(i))];
else
continue;
end
end
x_realroots
x_realroots = 1×2
-3.6921 -0.7084
x_realroots2 = real(x_roots(imag(x_roots) == 0))
x_realroots2 = 2×1
-3.6921 -0.7084
Note that you don't even need a loop.
Also, 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
  3 件のコメント
Dyuman Joshi
Dyuman Joshi 2023 年 11 月 21 日
編集済み: Dyuman Joshi 2023 年 11 月 21 日
"You are trying to us xroots, a vector of complex numbers as the index in your for loop."
@Les Beckham, For loop index values can be anything. Do not confuse them with array indices.
And OP is not trying to use the for loop indices as array indices.
Les Beckham
Les Beckham 2023 年 11 月 21 日
Good point. I had misinterpreted what they were trying to do. Of course, the real "Matlab way" is to not have a loop in the first place.
w_vec = [0.01 0.04 0.02 0.04 0.03];
x_roots = roots(w_vec)
x_roots =
-3.6921 + 0.0000i 0.2003 + 1.0521i 0.2003 - 1.0521i -0.7084 + 0.0000i
x_realroots2 = real(x_roots(imag(x_roots) == 0))
x_realroots2 = 2×1
-3.6921 -0.7084

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

製品


リリース

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by