how to sum elements of array using different way - matlab

i know one simple way to sum elements of array is following code
sum=0;
>> a=[12 31,45,10];
>> n=length(a);
>> for i=1:n
sum=sum+a(i);
end
>> sum
sum =
98
also there is another way to do it ,like this one
>> sum=0;
>> for a=[10 21 23 45]
sum=sum+a;
end
>> sum
sum =
99
i want to know which one faster and why,maybe second one is equivalent of pointer in c++?please help me

Why not use:
a = [10 21 23 45];
yourSum = sum(a);
To answer your question further: check your results using tic and toc

Related

Count number of elements in a specific range in an array [duplicate]

I have a huge vector. I have to count values falling within certain ranges.
the ranges are like 0-10, 10-20 etc. I have to count the number of values which fall in certain range.
I did something like this :
for i=1:numel(m1)
if (0<m1(i)<=10)==1
k=k+1;
end
end
Also:
if not(isnan(m1))==1
x=(0<m1<=10);
end
But both the times it gives array which contains all 1s. What wrong am I doing?
You can do something like this (also works for non integers)
k = sum(m1>0 & m1<=10)
You can use logical indexing. Observe:
>> x = randi(40, 1, 10) - 20
x =
-2 17 -12 -9 -14 -14 15 4 2 -14
>> x2 = x(0 < x & x < 10)
x2 =
4 2
>> length(x2)
ans =
2
and the same done in one step:
>> length(x(0 < x & x < 10))
ans =
2
to count the values in a specific range you can use ismember,
if m1 is vector use,
k = sum(ismember(m1,0:10));
If m1 is matrix use k = sum(sum(ismember(m1,0:10)));
for example,
m1=randi(20,[5 5])
9 10 6 10 16
8 9 14 20 6
16 13 14 7 11
16 15 4 12 14
4 16 3 5 18
sum(sum(ismember(m1,1:10)))
12
Why not simply do something like this?
% Random data
m1 = 100*rand(1000,1);
%Count elements between 10 and 20
m2 = m1(m1>10 & m1<=20);
length(m2) %number of elements of m1 between 10 and 20
You can then put things in a loop
% Random data
m1 = 100*rand(1000,1);
nb_elements = zeros(10,1);
for k=1:length(nb_elements)
temp = m1(m1>(10*k-10) & m1<=(10*k));
nb_elements(k) = length(temp);
end
Then nb_elements contains your data with nb_elements(1) for the 0-10 range, nb_elements(2) for the 10-20 range, etc...
Matlab does not know how to evaluate the combined logical expression
(0<m1(i)<=10)
Insted you should use:
for i=1:numel(m1)
if (0<m1(i)) && (m1(i)<=10)
k=k+1;
end
end
And to fasten it up probably something like this:
sum((0<m1) .* (m1<=10))
Or you can create logical arrays and then use element-wise multiplication. Don't know how fast this is though and it might use a lot of memory for large arrays.
Something like this
A(find((A>0.2 .* (A<0.8)) ==1))
Generate values
A= rand(5)
A =
0.414906 0.350930 0.057642 0.650775 0.525488
0.573207 0.763477 0.120935 0.041357 0.900946
0.333857 0.241653 0.421551 0.737704 0.162307
0.517501 0.491623 0.016663 0.016396 0.254099
0.158867 0.098630 0.198298 0.223716 0.136054
Find the intersection where the values > 0.8 and < 0.2. This will give you two logical arrays and the values where A>0.2 and A<0.8 will be =1 after element-wise multiplication.
find((A>0.2 .* (A<0.8)) ==1)
Then apply those indices to A
A(find((A>0.2 .* (A<0.8)) ==1))
ans =
0.41491
0.57321
0.33386
0.51750
0.35093
0.76348
0.24165
0.49162
0.42155
0.65077
0.73770
0.22372
0.52549
0.90095
0.25410

Matlab: How do I use two nested for-loops to generate a consecutive list of numbers in ascending order?

I would like to obtain an array of consecutive numbers from 1 to the product of the limits of two nested loops. I hope the example below will clarify the question. If I have the nested loop:
for i = 1:limit_loop_1
for j = 1:limit_loop_2
a = ???;
disp(a)
end
end
I would like to obtain a = (1:(limit_loop_1*limit_loop_2))'
For example, having:
for i = 1:3
for j = 1:5
a = ????;
disp(a)
end
end
I would like to get:
a=
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
I found similar questions for Java (like here), but nothing for Matlab. Thanks in advance.
Edit: I need this particular procedure because I will use the index to refer to another array. So, if I have for example a 3D array A of size (100,1,15) within the nested loops, I want to consider each one of the 15 elements of the array at each iteration. In code this would be:
for k = 1:100
for i = 1:3
for j = 1:5
something = A (k,1,????)
end
end
end
That is why ????? should go from 1 to 15. Hope this clarify my issue.
Obviously the solution you already provided (a = (1:(limit_loop_1*limit_loop_2))') is correct and absolutely nice. However if you must use a nested loop, just treat a as an external counter
a=0;
for i = 1:3
for j = 1:5
a = a+1;
disp(a)
end
end
This basically counts how many iteration are made by using the nested loop (3*5 in this case).
Or if you want to exploit the indices i and j you can re-adapt the Java example in Matlab by taking into account that in Matlab the indices start at 1 whereas in Java they start at 0:
for i = 1:3
for j = 1:5
c =1+(j-1)*1+(i-1)*(5);
disp(c)
end
end
I have no idea why you'd want to do it this way, but I'll take you at your word. This will give you the results you require:
for ii = 1:3
for jj = 1:5
a = 5*(ii-1)+jj;
disp(a)
end
end
(I changed your loop variables from i and j because they're the imaginary unit variables by default, and some folks get upset if you overwrite them.)
Results:
>> loop15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Save to array in for loop, with steps - Matlab

Okay, this is a bit tricky to explain, but I have a long .txt file with data (only one column). It could look like this:
data=[18
32
50
3
19
31
48
2
18
33
51
4]
Now, every fourth value (e.g. 18, 19, 18) represents the same physical quantity, just from different measurements. Now, I want Matlab to take every fourth value and put it into an array X=[18 19 18], and like wise for the other quantities.
My solution so far looks like this:
for i=1:3;
for j=1:4:12;
X(i)=data(j);
end
end
... in this example, because there are three of each quantity (therefore i=1:3), and there are 12 datapoints in total (therefore j=1:4:12, in steps of 4). data is simply the loaded list of datapoints (this works fine, I can test it in command window - e.g. data(2)=32).
My problem, doing this, is, that my array turns out like X=[18 18 18] - i.e. only the last iteration is put into the array
Of course, in the end, I would like to do it for all points; saving the 2nd, 6th, and 10th datapoint into Y and so on. But this is simply having more for-loops I guess.
I hope this question makes sense. I guess it is an easy problem to solve.
Why don't you just do?
>> X = data(1:4:end)
X =
18
19
18
>> Y = data(2:4:end)
Y =
32
31
33
You can reshape the data and then either split it up into different variables or just know that each column is a different variable (I'm now assuming each measurement occurs the same number of times i.e. length(data) is a multiple of 4)
data = reshape(data, 4, []).';
So now if you want
X = data(:,1);
Y = data(:,2);
%// etc...
But also you could just leave it as data all in one variable since calling data(:,1) is hardly more hassle than X.
Now, you should NOT use for-loops for this, but I'm gong to address what's wrong with your loops and how to solve this using loops purely as an explanation of the logic. You have a nested loop:
for i=1:3;
for j=1:4:12;
X(i)=data(j);
end
end
Now what you were hoping was that i and j would each move one iteration forward together. So when i==1 then j==1, when i==2 then j==5 etc but this is not what happens at all. To best understand what's going on I suggest you print out the variables at each iteration:
disp(sprintf('i: \tj:'));
for i=1:3;
for j=1:4:12;
disp(sprintf(' %d\t %d',i,j));
end
end
This prints out
i: j:
1 1
1 5
1 9
2 1
2 5
2 9
3 1
3 5
3 9
What you wanted was
disp(sprintf('i: \tj:'));
for i=1:3;
disp(sprintf(' %d\t %d',i,4*i-3));
end
which outputs:
i: j:
1 1
2 5
3 9
applied to your problem:
%// preallocation!
X = zeros(size(data,1)/4, 1)
for i=1:3
X(i)=data(i*4 - 3);
end
Or alternatively you can keep a separate count of either i or j:
%// preallocation!
X = zeros(size(data,1)/4, 1)
i = 1;
for j=1:4:end;
X(i)=data(j);
i = i+1;
end
Just for completeness your own solution should have read
i = 0;
for j=1:4:12;
i = i+1;
X(i)=data(j);
end
Of course am304's answer is a better way of doing it.

Recurring Function with Matrix Input

I believe most functions in MATLAB should be able to receive matrix input and return the output in the form of matrix.
For example sqrt([1 4 9]) would return [1 2 3].
However, when I tried this recurring factorial function:
function k = fact(z)
if z ~= 0
k = z * fact(z-1);
else
k = 1;
end
end
It works perfectly when a number is input into fact. However, when a matrix is input into fact, it returns the matrix itself, without performing the factorial function.
E.g.
fact(3) returns 6
fact([1 2 3]) returns [1 2 3] instead of [1 2 6].
Any help is appreciated. Thank you very much!
Since MATLAB is not known to be good with recursive functions, how about a vectorized approach? Try this for a vector input -
mat1 = repmat([1:max(z)],[numel(z) 1])
mat1(bsxfun(#gt,1:max(z),z'))=1
output1 = prod(mat1,2)
Sample run -
z =
1 2 7
output1 =
1
2
5040
For the sake of answering your original question, here's the annoying loopy code for a vector or 2D matrix as input -
function k1 = fact1(z1)
k1 = zeros(size(z1));
for ii = 1:size(z1,1)
for jj = 1:size(z1,2)
z = z1(ii,jj);
if z ~= 0
k1(ii,jj) = z .* fact1(z-1);
else
k1(ii,jj) = 1;
end
end
end
return
Sample run -
>> fact1([1 2 7;3 2 1])
ans =
1 2 5040
6 2 1
You can use the gamma function to compute the factorial without recursion:
function k = fact(z)
k = gamma(z+1);
Example:
>> fact([1 2 3 4])
ans =
1 2 6 24
Not sure if all of you know, but there is an actual factorial function defined in MATLAB that can take in arrays / matrices of any size, and computes the factorial element-wise. For example:
k = factorial([1 2 3 4; 5 6 7 8])
k =
1 2 6 24
120 720 5040 40320
Even though this post is looking for a recursive implementation, and Divakar has provided a solution, I'd still like to put my two cents in and suggest an alternative. Also, let's say that we don't have access to factorial, and we want to compute this from first principles. What I would personally do is create a cell array that's the same size as the input matrix, but each element in this cell array would be a linear index array from 1 up to the number defined for each location in the original matrix. You would then apply prod to each cell element to compute the factorial. A precondition is that no number is less than 1, and that all elements are integers. As such:
z1 = ... ; %// Define input matrix here
z1_matr = arrayfun(#(x) 1:x, z1, 'uni', 0);
out = cellfun(#prod, z1_matr);
If z1 = [1 2 3 4; 5 6 7 8];, from my previous example, we get the same output with the above code:
out =
1 2 6 24
120 720 5040 40320
This will obviously be slower as there is an arrayfun then cellfun call immediately after, but I figured I'd add another method for the sake of just adding in another method :) Not sure how constructive this is, but I figured I'd add my own method and join Divakar and Luis Mendo :)

How to compare array to a number for if statement?

H0 is an array ([1:10]), and H is a single number (5).
How to compare every element in H0 with the single number H?
For example in
if H0>H
do something
else
do another thing
end
MATLAB always does the other thing.
if requires the following statement to evaluate to a scalar true/false. If the statement is an array, the behaviour is equivalent to wrapping it in all(..).
If your comparison results in a logical array, such as
H0 = 1:10;
H = 5;
test = H0>H;
you have two options to pass test through the if-statement:
(1) You can aggregate the output of test, for example you want the if-clause to be executed when any or all of the elements in test are true, e.g.
if any(test)
do something
end
(2) You iterate through the elements of test, and react accordingly
for ii = 1:length(test)
if test(ii)
do something
end
end
Note that it may be possible to vectorize this operation by using the logical vector test as index.
edit
If, as indicated in a comment, you want P(i)=H0(i)^3 if H0(i)<H, and otherwise P(i)=H0(i)^2, you simply write
P = H0 .^ (H0<H + 2)
#Jonas's nice answer at his last line motivated me to come up with a version using logical indexing.
Instead of
for i=1:N
if H0(i)>H
H0(i)=H0(i)^2;
else
H0(i)=H0(i)^3;
end
end
you can do this
P = zeros(size(H0)); % preallocate output
test = H0>H;
P(test) = H0(test).^2; % element-wise operations
% on the elements for which the test is true
P(~test) = H0(~test).^3; % element-wise operations
% on the elements for which the test is false
Note that this is a general solution.
Anyway take a look at this: using ismemeber() function. Frankly not sure how do you expect to compare. Either greater than, smaller , equal or within as a member. So my answer might not be yet satisfying to you. But just giving you an idea anyway.
H0 = [0 2 4 6 8 10 12 14 16 18 20];
H = [10];
ismember(H,H0)
IF (ans = 1) then
// true
else
//false
end
Update Answer
This is super bruteforce method - just use it explain. You are better off with any other answers given here than what I present. Ideally what you need is to rip off greater/lower values into two different vectors with ^3 processing - I assume... :)
H0 = [0 2 4 6 8 10 12 14 16 18 20];
H = [10];
H0(:)
ans =
0
2
4
6
8
10
12
14
16
18
20
Function find returns indices of all values in H0 greater than 10 values in a linear index.
X = find(H0>H)
X =
7
8
9
10
11
Function find returns indices of all values in H0 lower than 10 in a linear index.
Y = find(H0<H)
Y =
1
2
3
4
5
6
If you want you can access each element of H0 to check greater/lower values or you can use the above matrices with indices to rip the values off H0 into two different arrays with the arithmetic operations.
G = zeros(size(X)); // matrix with the size = number of values greater than H
J = zeros(size(Y)); // matrix with the size = number of values lower than H
for i = 1:numel(X)
G(i) = H0(X(i)).^3
end
G(:)
ans =
1728
2744
4096
5832
8000
for i = 1:numel(Y)
J(i) = H0(Y(i)).^2
end
J(:)
ans =
0
4
16
36
64
100