Fibonacci function not accepting 0 and not displaying the last term only - matlab

I wrote a function that displays the Fibonacci sequence up to the nth term. The code runs fine, but I want to make two changes and am not sure how to do so.
Here is my code:
function [ F ] = get_fib( k )
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
end
The first problem is that the code does not accept 0 as an input. I tried changing the function to:
function [ F ] = get_fib( k )
F(0) = 0;
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
end
But the following error appears:
Attempted to access F(0); index must be a positive integer or logical.
Error in get_fib (line 2)
F(0) = 0;
I would also like the code to display the last term in the sequence, rather than the entire sequence.
I changed the function to:
function [ F ] = get_fib( k );
F(1) = 1;
F(2) = 1;
i = 3;
while k >= i;
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
term = F(k)
end
but the sequence it still being assigned to ans.
How can I make my function accept 0 as an argument and only display the last term of the sequence?

First let's get your function to output just the last item in the sequence. You're setting term like this:
term = F(k);
Which is good (notice I added the ; at the end, though). But the return value from your function is F. You need to change it to term.
function [ term ] = get_fib( k )
%// ^^^^- change this ^-- semicolon not necessary here
Now, to handle an input of 0, you can add a special check for zero:
function [ term ] = get_fib( k )
if k == 0
term = [];
return;
end
while k >= i
%// ^-- semicolon not needed here, either
<the rest of your code>
The semicolons after the function header and the while statement don't hurt anything, they just represent empty statements. But they might be misleading, so it's best to remove them.
The semicolon after the assignment to term prevents the ans = ... line from printing out to the console.

To address your first problem, F(0) is not a valid call. This is because MATLAB indexing starts from 1. In other words, the first element of a matrix is index 1. There is no 0th index of a matrix in MATLAB. See here for why MATLAB indexing starts from 1. What I would recommend to address this is to shift your output array by one index.
Thus, your code for the function should be:
function [ F ] = get_fib( k )
k = k + 1
F(1) = 0; % 0th Fibonacci term
F(2) = 1; % 1st Fibonacci term
F(3) = 1; % 2nd Fibonacci term
i = 4;
while k >= i
F(i) = F(i-1) + F(i-2);
i = i + 1;
end
term = F(k)
end
To address your second problem, it would depend on what you want. Do you (1) want the last term in the sequence to be returned when you call term = get_fib(k)or (2) want the last term of the sequence to be displayed and the entire sequence to be returned?
To achieve (1), fix the top line of your code to function term = F(k). To achieve (2), call the function with F = get_fib(some_number), as #rayryeng stated.

Since others already pointed out how to fix your code, I'd like to show you one approach to calculate the nth Fibonacci number without relying on the F(n-1) and F(n-2) terms calculation.
It involves the golden ratio, and you can read more about its relationship to the Fibonacci sequence here.
function [ F ] = get_fib( n )
% Changed your input variable from k to n (standard notation)
Phi = (1+sqrt(5))/2; % Golden ratio value
F = round((Phi^n - ((-1)^n)/(Phi^n))/sqrt(5)); %nth fibonacci number
end
Since you are only interested in the last value of the sequence, it could speed up the calculation for large values of n.
Note i have rounded the output (F) to avoid floating point arithmetic errors.

Related

Error in code, a method to compute sqrt (a)

One of the methods to compute sqrt(a), a>0 is
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1)), n = 1, 2, …,
with X0=1 and X1=a (That is, it is known that lim n-> infin of Xn = sqrt(a)
Write a function [sqa, nitr] = mySqrt(a) which implements this calculation. The function should use a while-loop, terminate when the difference between Xn+1 and Xn becomes smaller than eps(10*a), and output Xn+1 in sqa and the value of n at which the while-loop was terminated in nitr. Test your function for a = 103041.
I have written this but it does not work
function [sqa, nitr] = mySqrt (a)
%[sqa, nitr] = mySqrt (a)
% computes square root of a
% sqa = a;
sqaprev = a;
nitr = 0;
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1))); %find the second term
sqa= X(n+1)
while abs (sqaprev-sqa) >= eps (10*a)
sqaprev = sqa;
sqa = (1/2) *(sqaprev+ (a/sqaprev));
nitr = nitr + 1;
end %while
end
i get the error:
Unrecognized function or variable 'X'.
Error in mySqrt (line 7)
X(n+1) = (a + (X(n)*X(n-1))/(X(n)+X(n-1))); %find the second term
Could someone help me ?
You should start with declaring your variables and assigning them values
X(1)=1;
X(2)=a;
n=2;
Then in the loop you apply the given recursion formula, not the Heron/Babylonian formula that got from somewhere else.
According to the algorithm you presented for the square root, you can try the code below
function [sqa, n] = mySqrt(a)
n = 2; % start from 2
X = [1,a]; % initial value for sequence X
while true % repeat procedure until termination condition is reached
X(n+1) = (a + (X(n)*X(n-1)))/(X(n)+X(n-1)); % update sequence X by assigning new values
if abs(X(n+1)-X(n)) <= eps(10*a) % termination condition
break;
end
n = n + 1;
end
sqa = X(end); % return the last element of X as the square root
end
such that
>> [sqa,n] = mySqrt(a)
sqa = 321.00
n = 20

Output 1, 0.5, or 0 depending if a matrix elements are prime, 1, or neither

I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.

Error while calculating limit - Conversion to logic from syms is not possible - MATLAB -2014a

I want to calculate the limit of log(CR(r))/log(r) as r tends to 0.
MATLAB code is written below.
function cd = CD(data)
syms r
cd = limit(log(CR(r,data))/log(r),r,0) ;
end
function val = hf(xi,xj,r)
dis = abs(xi-xj);
if(dis <= r)
val = 1;
else
val = 0 ;
end
end
function cr = CR(r,data)
N = length(data);
sum = 0;
for i = 1 : N
for j = i+1 : N
sum = sum + hf(data(i),data(j),r);
end
end
cr = sum/(N*(N-1));
end
Error:-
Well, the error message says it all really:
You can't use a symbolic variable in an equality check. How can you know if dis <= r when r doesn't have a value?
I'm obligated to say this:
Don't use sum as a variable name! It's a very important and useful builtin function. You're making it useless when doing that.
i and j are bad variable names in MATLAB, since they denote the imaginary unit (sqrt(-1)).
Also, did I remember to say: Dont use sum as a variable name!
PS! Your hf-function is equivalent to:
function val = hf(xi,xj,r)
var = abs(xi-xj) <= r; % Still doesn't work since r is symbolic
end

Stopping the output of a for cycle in matlab

I'm facing an issue with this simple Fibonacci number generator program:
function f = fibonr(n)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
end
If I want to display only the n-th number of the sequence, what adjustments should I make?
function f = fibonr(n)
f = zeros(n,1); %//initialise the output array
f(1,1) = 1;
f(2,1) = 1;
for ii = 3:n
f(ii,1) = f(ii-1,1) + f(ii-2,1);
end
%//create a string with text and variables
str = sprintf('The %d th number in the Fibonacci sequence is %d',n,f(ii,1));
disp(str) %//display your output.
end
first up: don't use i as a variable. Secondly, I switched to using column vectors, since MATLAB processes them faster, as well as I initialised the array, which is way faster (hence the shiny orange wiggles below your f(i)= line).
Call your function:
output = fibonr(10);
The 10 th number in the Fibonacci sequence is 55
If you use e.g. n=20 and still want the 10th argument just call output(10)
if you want the specified output right away you can use nargin. This code will give you all of the sequence if you call fibonr(n), or you can specify a vector to get the fibonacy numbers at said positions. If you are interested in both, your specified output and all the numbers, you can call the function with:
[output, fibnumbers] = fibonr(n,v);
function [output,f] = fibonr(n,v)
f(1) = 1;
f(2) = 1;
for i = 3:n
f(i) = f(i-1) + f(i-2);
end
if nargin() > 1
output = f(v);
else
output = f;
end

Plotting own function in scilab

Hey i have an issuse with plotting my own function in scilab.
I want to plot the following function
function f = test(n)
if n < 0 then
f(n) = 0;
elseif n <= 1 & n >= 0 then
f(n) = sin((%pi * n)/2);
else
f(n) = 1;
end
endfunction
followed by the the console command
x = [-2:0.1:2];
plot(x, test(x));
i loaded the function and get the following error
!--error 21
Invalid Index.
at line 7 of function lala called by :
plot(x, test(x))
Can you please tell me how i can fix this
So i now did it with a for loop. I don't think it is the best solution but i can't get the other ones running atm...
function f = test(n)
f = zeros(size(n));
t = length(n);
for i = 1:t
if n(i) < 0 then
f(i) = 0;
elseif n(i) <= 1 & n(i) >= 0
f(i) = sin((%pi * n(i)/2));
elseif n(i) > 1 then
f(i) = 1;
end
end
endfunction
I guess i need to find a source about this issue and get used with the features and perks matlab/scilab have to over :)
Thanks for the help tho
The original sin is
function f = test(n)
(...)
f(n) = (...)
(...)
endfunction
f is supposed to be the result of the function. Therefore, f(n) is not "the value that the function test takes on argument n", but "the n-th element of f". Scilab then handles this however it can; on your test case, it tries to access a non-integer index, which results in an error. Your loop solution solves the problem.
Replacing all three f(n) by f in your first formulation makes it into something that works... as long as the argument is a scalar (not an array).
If you want test to be able to accept vector arguments without making a loop, the problem is that n < 0 is a vector of the same size as n. My solution would use logical arrays for indexing each of the three conditions:
function f = test(n)
f = zeros(size(n));
negative = (n<0);//parentheses are optional, but I like them for readability
greater_than_1 = (n>1);
others = ~negative & ~greater_than_1;
f(isnegative)=0;
f(greater_than_1)=1;
f(others) = sin(%pi/2*n(others));
endfunction