Dividing by a range values - matlab

I am a bit confused with the below output:
>> 1:6/3
ans =
1 2
But
>> 1/3
ans =
0.3333
Also
>> 1:24/3
ans =
1 2 3 4 5 6 7 8
It seems like MATLAB is outputting only values of number divisible in range 1-24 by 3? But why not for those which are not fully divisible by 3?
Also I am not able to understand the below output:
>> 1:24/3:2
ans =
1
Similarly
>> 1:6/2 * 2
ans =
1 2 3 4 5 6

It's simple enough:
1:6/3 implies 1:2 which is a vector ranging from 1 to 2.
1/3 is simply a straight forward division.
1:24/3 implies 1:8 which is a vector ranging from 1 to 8.
1:24/3:2 implies 1:8:2 which is a vector ranging from 1 to 2 with a difference of 8 between each element. This just leaves you with 1 as the next possible iteration, 9 would be greater than 2.
1:6/2 * 2 implies 1:3*2 which implies 1:6. This is a vector ranging from 1 to 6.

This is an operator precedence problem. / has higher precedence level than :.
Therefore 1:6/3 is equivalent to 1:(6/3), while you wanted to compute (1:6)/3
Try with parenthesis to observe different results:
>> (1:6)/3
>> (1:24)/3
>> (1:24)/(3:2)
>> ((1:6)/2)*2

You might be aware of the BODMAS rule which says that the
B Brackets first
O Orders (ie Powers and Square Roots, etc.)
DM Division and Multiplication (left-to-right)
AS Addition and Subtraction (left-to-right)
When modified to the usage in mathematics it added a few more operators according to which / has a higher precedence over :
Therefore you get erroneous results. You can check this thing by implementing more brackets.

Related

Output a matrix size n x m, 1 when the sum of the indices is even, 0 otherwise

I'm attempting the following as a hobby, not as homework. In Computer Programming with MATLAB: J. Michael Fitpatrick and Akos Ledeczi, there is a practice problem that asks this:
Write a function called alternate that takes two positive integers, n and m, as input arguments (the function does not have to check the format of the input) and returns one matrix as an output argument. Each element of the n-by-m output matrix for which the sum of its indices is even is 1.
All other elements are zero.
A previous problem was similar, and I wrote a very simple function that does what it asks:
function A = alternate(n,m)
A(1:n,1:m)=0;
A(2:2:n,2:2:m)=1;
A(1:2:n,1:2:m)=1;
end
Now my question is, is that good enough? It outputs exactly what it asks for, but it's not checking for the sum. So far we haven't discussed nested if statements or anything of that sort, we just started going over very basic functions. I feel like giving it more functionality would allow it to be recycled better for future use.
Great to see you're learning, step 1 in learning any programming language should be to ensure you always add relevant comments! This helps you, and anyone reading your code. So the first improvement would be this:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
A(1:n,1:m)=0; % Create the n*m array of zeros
A(2:2:n,2:2:m)=1; % All elements with even row and col indices: even+even=even
A(1:2:n,1:2:m)=1; % All elements with odd row and col indicies: odd+odd=even
end
You can, however, make this more concise (discounting comments), and perhaps more clearly relate to the brief:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
% Sum of row and col indices. Uses implicit expansion (R2016b+) to form
% a matrix from a row and column array
idx = (1:n).' + (1:m);
% We want 1 when x is even, 0 when odd. mod(x,2) is the opposite, so 1-mod(x,2) works:
A = 1 - mod( idx, 2 );
end
Both functions do the same thing, and it's personal preference (and performance related for large problems) which you should use.
I'd argue that, even without comments, the alternative I've written more clearly does what it says on the tin. You don't have to know the brief to understand you're looking for the even index sums, since I've done the sum and tested if even. Your code requires interpretation.
It can also be written as a one-liner, whereas the indexing approach can't be (as you've done it).
A = 1 - mod( (1:n).' + (1:m), 2 ); % 1 when row + column index is even
Your function works fine and output the desired result, let me propose you an alternative:
function A = alternate(n,m)
A = zeros( n , m ) ; % pre-allocate result (all elements at 0)
[x,y] = meshgrid(1:m,1:n) ; % define a grid of indices
A(mod(x+y,2)==0) = 1 ; % modify elements of "A" whose indices verify the condition
end
Which returns:
>> alternate(4,5)
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
initialisation:
The first line is the equivalent to your first line, but it is the cannonical MATLAB way of creating a new matrix.
It uses the function zeros(n,m).
Note that MATLAB has similar functions to create and preallocate matrices for different types, for examples:
ones(n,m) Create
a matrix of double, size [n,m] with all elements set to 1
nan(n,m) Create a
matrix of double, size [n,m] with all elements set to NaN
false(n,m) Create a
matrix of boolean size [n,m] with all elements set to false
There are several other matrix construction predefined function, some more specialised (like eye), so before trying hard to generate your initial matrix, you can look in the documentation if a specialised function exist for your case.
indices
The second line generate 2 matrices x and y which will be the indices of A. It uses the function meshgrid. For example in the case shown above, x and y look like:
| x = | y = |
| 1 2 3 4 5 | 1 1 1 1 1 |
| 1 2 3 4 5 | 2 2 2 2 2 |
| 1 2 3 4 5 | 3 3 3 3 3 |
| 1 2 3 4 5 | 4 4 4 4 4 |
odd/even indices
To calculate the sum of the indices, it is now trivial in MATLAB, as easy as:
>> x+y
ans =
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Now we just need to know which ones are even. For this we'll use the modulo operator (mod) on this summed matrix:
>> mod(x+y,2)==0
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
This result logical matrix is the same size as A and contain 1 where the sum of the indices is even, and 0 otherwise. We can use this logical matrix to modify only the elements of A which satisfied the condition:
>> A(mod(x+y,2)==0) = 1
A =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
Note that in this case the logical matrix found in the previous step would have been ok since the value to assign to the special indices is 1, which is the same as the numeric representation of true for MATLAB. In case you wanted to assign a different value, but the same indices condition, simply replace the last assignment:
A(mod(x+y,2)==0) = your_target_value ;
I don't like spoiling the learning. So let me just give you some hints.
Matlab is very efficient if you do operations on vectors, not on individual elements. So, why not creating two matrices (e.g. N, M) that holds all the indices? Have a look at the meshgrid() function.
Than you might be able find all positions with an even sum of indices in one line.
Second hint is that the outputs of a logic operation, e.g. B = A==4, yields a logic matrix. You can convert this to a matrix of zeros by using B = double(B).
Have fun!

Why are multiple, consecutive plusses allowable syntax in MATLAB?

Does anyone know why this works in MATLAB?
>> 1 ++ 2
ans =
3
Coming from coding in C, python, Java etc, I find it most counterintuitive that this should work at all. Presumably there's something important about the parser that I don't understand?
There's a difference between plus and uplus. I suspect MATLAB takes the first + as plus, and all the others as uplus. Since uplus is by default just "return what's behind", you add 1 and 2, and use a lot of "return what's behind" in between.
a=2;
c=+a % unitary plus
c =
2
1+2 % addition
ans =
3
1+++2 % addition and two uplusses
ans =
3
The reason uplus exists is to allow operator overloading in classes. The same works in other languages, e.g. in C#, to allow for operator overloading in confined classes.
The other reason mentioned in that C# thread is that is changes unsigned shorts to integers, which is not the case for MATLAB:
d=uint8(1)
d =
uint8
1
+d
ans =
uint8
1
a=+d
a =
uint8
1
It does, however, convert a boolean to a double, thanks to Cris Lunego for pointing that out:
+true
ans =
1
+false
ans =
0
The following however remains a mystery to me, inspired by Sanjay Manohar's comment:
>> [1 ++ 2]
ans =
1 2 % Two unary plusses
>> [1 + + 2]
ans =
3 % A normal plus and a unary one
>> [1++2]
ans =
3 % A normal plus and a unary one
The same works with multiple plusses, [1 +++..+++ 2], so with all plusses consecutively in the middle generates [1 2], all other combinations (as far as I tested) result in 3. I asked a separate question about this: Why do the plus and unary plus behave strange in array syntax?

How to get the maximal values and the related coordinates? [duplicate]

suppose that we are determine peaks in vector as follow:
we have real values one dimensional vector with length m,or
x(1),x(2),.....x(m)
if x(1)>x(2) then clearly for first point peak(1)=x(1);else we are then comparing x(3) to x(2),if x(3)
[ indexes,peaks]=function(x,m);
c=[];
b=[];
if x(1)>x(2)
peaks(1)=x(1);
else
for i=2:m-1
if x(i+1)< x(i) & x(i)>x(i-1)
peak(i)=x(i);
end;
end
end
end
peaks are determined also using following picture:
sorry for the second picture,maybe it is not triangle,just A and C are on straight line,but here peak is B,so i can't continue my code for writing algorithm to find peak values in my vector.please help me to continue it
updated.numercial example given
x=[2 1 3 5 4 7 6 8 9]
here because first point is more then second,so it means that peak(1)=2,then we are comparing 1 to 3,because 3 is more then 1,we now want to compare 5 to 3,it is also more,compare 5 to 4,because 5 is more then 4,then it means that peak(2)=5,,so if we continue next peak is 7,and final peak would be 9
in case of first element is less then second,then we are comparing second element to third one,if second is more then third and first elements at the same time,then peak is second,and so on
You could try something like this:
function [peaks,peak_indices] = find_peaks(row_vector)
A = [min(row_vector)-1 row_vector min(row_vector)-1];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end
Save it as find_peaks.m
Now, you can use it as:
>> A = [2 1 3 5 4 7 6 8 9];
>> [peaks, peak_indices] = find_peaks(A)
peaks =
2 5 7 9
peak_indices =
1 4 6 9
This would however give you "plateaus" as well (adjacent and equal "peaks").
You can use diff to do the comparison and add two points in the beginning and end to cover the border cases:
B=[1 diff(A) -1];
peak_indices = find(B(1:end-1)>=0 & B(2:end)<=0);
peaks = A(peak_indices);
It returns
peak_indices =
1 4 6 9
peaks =
2 5 7 9
for your example.
findpeaks does it if you have a recent matlab version, but it's also a bit slow.
This proposed solution would be quite slow due to the for loop, and you also have a risk of rounding error due to the fact that you compare the maximal value to the central one instead of comparing the position of the maximum, which is better for your purpose.
You can stack the data so as to have three columns : the first one for the preceeding value, the second is the data and the third one is the next value, do a max, and your local maxima are the points for which the position of the max along columns is 2.
I've coded this as a subroutine of my own peak detection function, that adds a further level of iterative peak detection
http://www.mathworks.com/matlabcentral/fileexchange/42927-find-peaks-using-scale-space-approach

Matlab matrices dimension

I am new to matlab and just wondering if you guys can help me out with this problem.
For instance, I have two matrices:
A = [X1 X2 X3 X4]
B = [Y1; Y2; Y3]
now what I really want to achieve is to multiply these two matrices in this way:
[X1Y1 X2Y1 X3Y1 X4Y1;
X1Y2 X2Y2 X3Y2 X4Y2;
X1Y3 X2Y3 X3Y3 X4Y3;
.... and so on]
I tried using A(1,:).*B(:,1) but matlab is saying that matrix dimensions must agree.
I just don't know how to manipulate this on matlab but in excel is possible.
This is a simple outer product. kron is not needed (although it will work.) bsxfun is wild overkill, although will yield what you have asked for. repmat is inappropriate, because while it will help you do what you wish, it replicates the arrays in memory, using more resources than are needed. (Avoid using inefficient programming styles when there are good ones immediately at your disposal.)
All you need use is the simple * operator.
A is a row vector. B a column vector.
C = B*A
will yield the result C(i,j)=B(i)*A(j), which is exactly what you are looking for. Note that this works because B is 3x1 and A is 1x4, so the "inner" dimensions of B and A do conform.
In MATLAB, IF you are unsure if something works, TRY IT!
A = [1 2 3 4];
B = [1;2;3];
C = B*A
ans =
1 2 3 4
2 4 6 8
3 6 9 12
See that kron did indeed work, although I'd bet that use of kron here is probably less efficient than is the simple outer product multiply.
C = kron(B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
As well, bsxfun will work here too, although since we are using a general tool to do something that a basic operator will do, I'd bet it is slightly less efficient.
C = bsxfun(#times,B,A)
C =
1 2 3 4
2 4 6 8
3 6 9 12
The WORST choice is repmat. Again, since it artificially replicates the vectors in memory FIRST, it must go out and grab big chunks of memory in the case of large vectors.
C = repmat(B,1,4).*repmat(A,3,1)
C =
1 2 3 4
2 4 6 8
3 6 9 12
I suppose for completeness, you could also have used meshgrid or ndgrid. See that it is doing exactly what repmat did, but here it explicitly creates new matrices. Again, this is a poor programming style when there are good tools to do exactly what you wish.
[BB,AA] = ndgrid(B,A)
BB =
1 1 1 1
2 2 2 2
3 3 3 3
AA =
1 2 3 4
1 2 3 4
1 2 3 4
C = BB.*AA
C =
1 2 3 4
2 4 6 8
3 6 9 12
What you need to understand is exactly why each of these tools COULD have been used for the job, and why they are different.
In Matlab there is * and .* and they are very different.
* is normal matrix multiplication which is what you want i.e. B*A, note the B must come first as the inner dimension must match. You can multiply a column by a row but not a row by a column (unless they have the same number of elements).
.* is element by element multiplication in which case the matrices must be exactly the same size and shape so for example [1 2 3].*[4 5 6] = [1*4 2*5 3*6] = [4 10 18]
Do not do a ".*". You should rather do a "*".
The ".*" is for index by index multiplication and should have given you [X1Y1 X2Y2 X3Y3] were they vectors have been equal in size.
If you do the regular multiplication "*", this is actually matrix multiplication.
I think you just need to transpose one of the vectors. You are multiplying a column vector (A(1,:)) with a row vector (B(:,1)). This should work:
C = A(1,:).*B(:,1)';

find peak values in matlab

suppose that we are determine peaks in vector as follow:
we have real values one dimensional vector with length m,or
x(1),x(2),.....x(m)
if x(1)>x(2) then clearly for first point peak(1)=x(1);else we are then comparing x(3) to x(2),if x(3)
[ indexes,peaks]=function(x,m);
c=[];
b=[];
if x(1)>x(2)
peaks(1)=x(1);
else
for i=2:m-1
if x(i+1)< x(i) & x(i)>x(i-1)
peak(i)=x(i);
end;
end
end
end
peaks are determined also using following picture:
sorry for the second picture,maybe it is not triangle,just A and C are on straight line,but here peak is B,so i can't continue my code for writing algorithm to find peak values in my vector.please help me to continue it
updated.numercial example given
x=[2 1 3 5 4 7 6 8 9]
here because first point is more then second,so it means that peak(1)=2,then we are comparing 1 to 3,because 3 is more then 1,we now want to compare 5 to 3,it is also more,compare 5 to 4,because 5 is more then 4,then it means that peak(2)=5,,so if we continue next peak is 7,and final peak would be 9
in case of first element is less then second,then we are comparing second element to third one,if second is more then third and first elements at the same time,then peak is second,and so on
You could try something like this:
function [peaks,peak_indices] = find_peaks(row_vector)
A = [min(row_vector)-1 row_vector min(row_vector)-1];
j = 1;
for i=1:length(A)-2
temp=A(i:i+2);
if(max(temp)==temp(2))
peaks(j) = row_vector(i);
peak_indices(j) = i;
j = j+1;
end
end
end
Save it as find_peaks.m
Now, you can use it as:
>> A = [2 1 3 5 4 7 6 8 9];
>> [peaks, peak_indices] = find_peaks(A)
peaks =
2 5 7 9
peak_indices =
1 4 6 9
This would however give you "plateaus" as well (adjacent and equal "peaks").
You can use diff to do the comparison and add two points in the beginning and end to cover the border cases:
B=[1 diff(A) -1];
peak_indices = find(B(1:end-1)>=0 & B(2:end)<=0);
peaks = A(peak_indices);
It returns
peak_indices =
1 4 6 9
peaks =
2 5 7 9
for your example.
findpeaks does it if you have a recent matlab version, but it's also a bit slow.
This proposed solution would be quite slow due to the for loop, and you also have a risk of rounding error due to the fact that you compare the maximal value to the central one instead of comparing the position of the maximum, which is better for your purpose.
You can stack the data so as to have three columns : the first one for the preceeding value, the second is the data and the third one is the next value, do a max, and your local maxima are the points for which the position of the max along columns is 2.
I've coded this as a subroutine of my own peak detection function, that adds a further level of iterative peak detection
http://www.mathworks.com/matlabcentral/fileexchange/42927-find-peaks-using-scale-space-approach