MatLab assigning only the first two variables in - matlab

I am trying to write a MatLab function to compute Fibonacci numbers. below is what I have but it comes up with an error about F(0).
??? Attempted to access F(0); index must be a positive integer or logical.
Error in ==> fibonacci at 11
F(0) = 0;
How do I tell matlab that the first two values in the array are 0 and 1??
function F = fibonacci( n )
%A fibonacci sequence is where the next term in the series is given by the
%sum of the pervious two terms
%Only valid if n is greater than or equal to 2
if n >= 2 ;
%Make an array with n terms
F = zeros (1,n);
%run a for loop from 2 to n
for i = 2:n;
F(0) = 0;
F(1) = 1;
F(i) = F(i-1) + F(i-2)
end
end
end

Your formatting is a bit off, but it seems like you are assigning a value to the zero-index of an array. As far as I know MatLab uses 1 as the index of the first item in an array.
If you change your if n>=2 to if >=3 and set the 1 and 2 index items instead of the 0 and 1 items you should be well on your way.
See also Is zero based indexing available in MATLAB

MATLAB uses 1-based indexing, which means you should rewrite indices to reflect this shift, by replacing your n variables with n+1. This starts the fibonacci at 0, but indexed to 1, 1 at 2, 1 at 3, 2 at 4, 3 at 5, and so on to your "n"th term, now be indexed at n+1.

Related

Explanation for a function within xcorr in MATLAB

Looking within the xcorr function, most of it is pretty straightforward, except for one function within xcorr called "findTransformLength".
function m = findTransformLength(m)
m = 2*m;
while true
r = m;
for p = [2 3 5 7]
while (r > 1) && (mod(r, p) == 0)
r = r / p;
end
end
if r == 1
break;
end
m = m + 1;
end
With no comments, i fail to understand what this function is meant to acheive and what is the significance of p = [2 3 5 7]. Why those numbers specifically? Why not take a fixed FFT size instead? Is there a disadvantage(cause errors) to taking a fixed FFT size?
This part is used to get the integer closest to 2*m that can be written in the form:
Either:
m is already of this form, then the loop
for p = [2 3 5 7]
while (r > 1) && (mod(r, p) == 0)
r = r / p;
end
end
Will decrease r down to 1 and the break will be reached.
Or m has at least one other prime factor, and r will not reach 1. You go back to the look with m+1 and so on until you reach a number of the right form.
As per why they do this, you can see on the fft doc, in the Input arguments section:
n — Transform length [] (default) | nonnegative integer scalar
Transform length, specified as [] or a nonnegative integer scalar.
Specifying a positive integer scalar for the transform length can
increase the performance of fft. The length is typically specified as
a power of 2 or a value that can be factored into a product of small
prime numbers. If n is less than the length of the signal, then fft
ignores the remaining signal values past the nth entry and returns the
truncated result. If n is 0, then fft returns an empty matrix.
Example: n = 2^nextpow2(size(X,1))

Produce 6 different number by only use "randi" and some loops

I want to only use "randi" this function to produce the 6 different number randomly in matlab ,and the range of these 6 number is 1 ~ 12.
number=randi([1,12],1,6)
c=0;
for n=1:6%when "n" is 1 to 6
while c <= 6 %while c is less equal than 6,do the program below
c = c + 1; %c=c+1
if number(n) == number(c) %when the nth element is equal to cth element
number(n) = randi(12); %produce a random integer in the nth element
c = 0; %the reason why i set c=0 again is because i want to check again whether the new random integer is the same as cth element or not
end
end
end
final_number=number
but the result still show me like
1 "2" 6 11 "2" 3
5 "8" "8" 12 3 1
How do i improve my code to produce 6 different numbers.i don't want to always rely on the convenient matlab instruction too much,so my tags will also write c.hoping someone can help me to improve this
If you're trying to reproduce randsample (or randperm), why not just reproduce the algorithm MATLAB uses? (As far as we can tell...)
This is the Fisher-Yates shuffle. If you have a vector v, each iteration selects a random, previously unused element and puts it at the end of the unselected elements. If you do k iterations, the last k elements of the list are your random sample. If k equals the number of elements in v, you've shuffled the entire array.
function sample = fisher_yates_sample(v, k)
% Select k random elements without replacement from vector v
% if k == numel(v), this is simply a fisher-yates shuffle
for n = 0:k-1
randnum = randi(numel(v)-n); % choose from unused values
% swap elements v(end-n) and v(randnum)
v([end-n, randnum]) = v([randnum, end-n]);
end
sample = v(end-k+1:end);
end
Unlike MATLAB's version, mine requires a vector as input, so to get 6 random values in the range 1:12 you'd call the function like this:
>> fisher_yates_sample(1:12,6)
ans =
5 11 6 10 8 4
Since you're re-selecting single random numbers, when there is one occuring multiple times, why not just re-selecting all numbers at once?
% Initial selecting of random numbers.
number = randi([1, 12], 1, 6)
% While the amount of unique elements in numbers is less than 6:
while (numel(unique(number)) < 6)
% Re-select random numbers.
number = randi([1, 12], 1, 6)
end
And since you wrote, you specifically want to use the randi method, I guess there is a reason, you don't want to use randperm(12, 6)!?
What you are looking for is randperm. It produces a random permutation of a range of integers, so that if you select the first k numbers, you are sure that you get k unique integers in the range [1;n].
In your case, simply call:
randperm(12,6)

Any way for matlab to sum an array according to specified bins NOT by for iteration? Best if there is buildin function for this

For example, if
A = [7,8,1,1,2,2,2]; % the bins (or subscripts)
B = [2,1,1,1,1,1,2]; % the array
then the desired function "binsum" has two outputs, one is the bins, and the other is the sum. It is just adding values in B according to subscripts in A. For example, for 2, the sum is 1 + 1 + 2 = 4, for 1 it is 1 + 1 = 2.
[bins, sums] = binsum(A,B);
bins = [1,2,7,8]
sums = [2,4,2,1]
The elements in "bins" need not be ordered but must correspond to elements in "sums". This can surely be done by "for" iterations, but "for" iteration is not desired, because there is a performance concern. It is best if there is a build in function for this.
Thanks a lot!
This is another job for accumarray
A = [7,8,1,1,2,2,2]; % the bins (or subscripts)
B = [2,1,1,1,1,1,2]; % the array
sums = accumarray(A.', B.').';
bins = unique(A);
Results:
>> bins
bins =
1 2 7 8
sums =
2 4 0 0 0 0 2 1
The index in sums corresponds to the bin value, so sums(2) = 4. You can use nonzeros to remove the unused bins so that bins(n) corresponds to sums(n)
sums = nonzeros(sums).';
sums =
2 4 2 1
or, to generate this form of sums in one line:
sums = nonzeros(accumarray(A.', B.')).';
Another possibility is to use sparse and then find.
Assuming A contains positive integers,
[bins, ~, sums] = find(sparse(A, 1, B));
This works because sparse automatically adds values (third input) for matching positions (as defined by the first two inputs).
If A can contain arbitrary values, you also need a call to unique, and find can be replaced by nonzeros:
[bins, ~, labels]= unique(A);
sums = nonzeros(sparse(labels, 1, B));
Here is a solution using sort and cumsum:
[s,I]=sort(A);
c=cumsum(B(I));
k= [s(1:end-1)~=s(2:end) true];
sums = diff([0 c(k)])
bins = s(k)

how to compare all vector indexes with a constant value and switch the value of another variable (0 1) based on that

I have a 1x24 vector (a). I should define a command in Matlab which compare all 24 values of a vector (a) with a certain value (mean (b)) and if the vector (a) item is greater than certain value (mean (b)), ''I'' sets 1 and if the vector item is less than certain value ''I'' sets 0. I wrote the below code:
for i=1:length(a)
if a(i) >= mean(b)
I = 1;
else
I = 0;
end
end
But it implements the comparison only for the last index of vector a and sets I=0. How can I fix the command that do the comparison for all indexes of vector a?
In MATLAB, you can use the following syntax to do so:
I = a >= mean(b);
If you want to use your code for doing so, you'll need to initialize I as a vector, and modify its indices as follows:
I = zeros(length(a),1)
for ii=1:length(a)
if a(ii) >= mean(b)
I(ii) = 1;
else
I(ii) = 0;
end
end
You should read about logical indexing in matlab. You don't need for loops for what you are doing. For example, if you have,
rng(5);
a = rand(1,10);
b = 0.5;
then, I = a > b; will return a logical array with zeros and ones, where one indicates the position in the array where the given condition is satisfied,
I =
0 1 0 1 0 1 1 1 0 0
Using these indices, you can modify your original array. For example, if you wish to change all values of a greater than b to be 10, you would simply do,
a(a > b) = 10;
Specifically, if you need indices where the condition is satisfied, you can use, find(a > b), which in this example will give you,
ans =
2 4 6 7 8

How to check my matrix if its divisible by 12

im new to matlab and i've run into a slight problem. I want to check my matrix that generated random number if they are divisible by 12. Then i want to list number of digit divisible by 12 and the total sum of those.
clc
clear
format compact
a=4
b=0
N=50+a
R=randi([100+a,159+b], 1, N) % generate random no. from 100+a to 159 on a matrix 1xN
s1=0
N1=0
for i = 1
for j= 1:N
if rem(R,12)==0
N1=N1+1;
s1=s1+R(i,j);
else
N1=N1+0;
s1=s1+0;
end
end
end
numberof1=N1
sum1=s1
Your code isn't working because your are calling rem(R, 12) (remainder of all elements) as opposed to the remainder of the specific element (rem(R(i,j), 12)).
The better approach though would be to remove the for loop and generate a logical matrix the size of R that is true when that number is divisible by 12 and false otherwise by passing the entire matrix to rem.
is_divisible_by_12 = rem(R, 12) == 0;
Then we can use this to compute the sum of these by using this logical array as an index into R
subset = R(is_divisible_by_12);
number = numel(subset);
s1 = sum(subset);