Evaluation of a polynomial in SciLab - polynomial-math

Could you please help me find a mistake in my code?
I need to calculate the polynomial, with parameters the vector and the value of the variable.
I am not allowed to use the power sign (^)
I have got this code but it doesn't work and I don't see what I am doing wrong.
function f=veelTermEvaluatie(V,x)
f=V(1);
for i=2:length(V)
for j=0:i-1
if j=0 then x=x
else x=x*x
end
f=V(i)*x
end
end
endfunction
V=[1 2 3 4 5 6]
x=3

I first refactored your code, to remove the j=0 situation, since this does not change anything since x=x it can be skipped by starting at j=1. I also added some debug printing :
function f=veelTermEvaluatie(V,x)
f=V(1);
for i=2:length(V)
printf("\nI: %d --> ", i)
for j=1:i-1
x = x * x
printf("j: %d, x=%d ",j,x)
end
f=V(i)*x
end
return f
endfunction
After that it became clear that you multiply the same x, each and every time:
I: 2 --> j: 1, x=9
I: 3 --> j: 1, x=81 j: 2, x=6561
I: 4 --> j: 1, x=43046721 j: 2, x=-501334399 j: 3, x=0
I: 5 --> j: 1, x=0 j: 2, x=0 j: 3, x=0 j: 4, x=Inf
I: 6 --> j: 1, x=Inf j: 2, x=Inf j: 3, x=Inf j: 4, x=Inf j: 5, x=Inf
What also happens is that you update the value of f to the highest term, disregarding any other terms.
I think your meaning is to return all terms
So you should create a local x which is reset for every term.
Working example
function f=veelTermEvaluatie(V,x)
//Initialize the result to be a copy of the input
f=V;
// For each element in the input (except the first)
for i=2:length(V)
printf("\nI: %d --> ", i);
//Initialize a local x variable to the global x
new_x = x;
for j=1:i-1
// Update only the local x
new_x = new_x * x;
printf("j: %d, x=%d ",j,x);
end
// Multiply the value in the array with the local x value
f(i)=V(i)*new_x;
end
return f
endfunction
V=[1 2 3 4 5 6]
x=3
result = veelTermEvaluatie(V,x)
disp(result)
disp(sum(result))

Scilab has already a horner function so you don't need to reinvent the wheel. For example, to evaluate the polynomial 1+2*x+4*x^2+8*x^3 at x=-1,0,1 you can proceed as follows:
p = poly([1 2 4 8],'x','coeff')
pval = horner(p,[-1 0 1])
which yields the following output
--> p = poly([1 2 4 8],'x','coeff')
p =
2 3
1 +2x +4x +8x
--> pval = horner(p,[-1 0 1])
pval =
-5. 1. 15.

What you should do is implement the Horner scheme.
f=V(n)
for i from n-1 down to 0 do
f = f*x
f = f+V(i)
end for
return f
In the question, you return the array of values V(i)*x^(2^i), in the previous answer, the array of evaluated terms V(i)*x^i is returned, but the value of the polynomial is the sum over those terms.
Please elaborate on the input format. Is V an array with index range 1:n? What is the intended relation between index and degree?

Related

What does this syntax [0:1:5] mean (do) in the context of the given code?

I don't understand how [0:1:5] is being used in the code below:
function [x , y] = plotTrajectory(Vo,O,t,g)
% calculating x and y values
x = Vo * cos(O) * t ;
y = Vo*(sin(O)*t)-(0.5*g*(t.^2));
plot (x,y);
hold on
end
for i = (0: (pi/8): pi);
[x,y] = plotTrajectory(10,i,[0:1:5],9.8);
end
Each of the parameters are being used to find particular X and Y values. O changes from 0 to pi in steps of pi/8 while Vo, t and g remain unchanged.
The t variable is simply an array from 0 to 5 in steps of 1 and so there are 6 time points defined all together. With these time points and with a particular value of O, but with the values of Vo, t and g being held constant throughout this entire endeavour, 6 X and Y points are defined and are thus plotted on a graph. A graph is generated for each value of O and thus a set of 6 different X and Y points are generated. Each graph with each value of O are all plotted on the same graph.
We can rewrite the above code in pseudo-code to make it easier to understand as follows:
for i = 0, pi/8, 2*pi/8, ..., pi
define Vo = 10
define O = i
define t = [0, 1, 2, 3, 4, 5]
define g = 9.8
run function plotTrajectory(Vo, O, t, g)
end
function plotTrajectory(Vo, O, t, g)
calculate x = Vo * cos(O) * t, for t = 0, 1, 2, 3, 4, 5
calculate y = Vo * (sin(O) * t) - (0.5 * g * t^2), for t = 0, 1, 2, 3, 4, 5
plot x and y for t = 0, 1, 2, 3, 4, 5 on the same graph
end

How to update the length of a vector in matlab if statement

I'm using MATLAB to write a function, which can find all elements in vector v that are equal to scalar a, and change each one of them to [b c], finally return the new vector w. If v = [1 2 5], a = 2, b = 4, c = 3, then the result is w = [1 4 3 5].
Below is my code
function w = change(v, a , b ,c )
for ii = 1:length(v)
if v(ii) == a
v_1 = v(1:ii-1);
v_2 = v(ii+1:length(v));
v_3 = [b c];
v = [v_1 v_3 v_2];
end
end
w = v;
end
However, the problem is: for statement will only read the length of the v before the first run of the loop, in this way, if the size of vector is increased, then length(v) in if statement will not be updated thus ii can not cover all the element indices. For example, if my input is ([1 2 2 2 3 2 4 5 6 2], 2, 4, 4), then with my code, for will stop at ii = 10, which is length of the old v, and give a wrong result [1 4 4 4 4 4 4 3 4 4 4 5 6 2], which does not change the last element (because ii doesn't cover 15).
My question is: how to update length(v) in if statement? or is there any other better way to finish this task?
Thank you very much.
I think this will be easier if you do it with cell arrays.
function w = change(v, a , b ,c )
cellV = num2cell(v);
cellW = cellfun(#(x)(subFunction(x,a,b,c)),cellV,'uni',0);
w = [cellW{:}];
end
function out = subFunction(val,a,b,c)
if (val == a)
out = [b c];
else
out = x;
end
end
A simpler method than checking each element in a loop is to find where the new elements will go, by using find(v==a) and just loop on those cases (taking care with the indexing!):
s = find(v==a);
v(end+1:end+numel(s))=0;
for ii=1:numel(s)
ind=s(ii)+ii;
v(ind-1:end)=[b c v(ind:end-1)];
end

How to "chop up" matrix in Matlab using combination of logical indexing and slicing?

I have a matrix M that looks similar to this:
M = [ 1, 2, 3, 0, 0;
1, 2, 0, 0, 0;
2, 3, 4, 5, 0;
4, 5, 6, 0, 0;
1, 2, 3, 4, 5;
]
I'm trying to get a column vector with the rightmost non-zero value of each row in A, but ONLY for the rows that have the first column == 1.
I'm able to calculate a filter for the rows:
r = M( :, 1 ) == 1;
> r = [ 1; 1; 0; 0; 1 ]
And I have a set of indices for "the rightmost non-zero value of each row in M":
> c = [ 3, 2, 4, 3, 5 ]
How do I combine these in a slicing of A in order to get what I'm looking for? I'm looking for something like:
A( r, c )
> ans = [ 3; 2; 5 ]
But doing this gets me a 3x3 matrix, for some reason.
The shortest way I can think of is as follows:
% Get the values of the last non-zero entry per row
v = M(sub2ind(size(M), 1:size(M,1), c))
% Filter out the rows that does not begin with 1.
v(r == 1)
This seems to work (I assume other operations defining r,c have been performed):
M(sub2ind(size(A),find(r==1).',c(r==1))).'
Short interpretation of the problem and solution:
M( r, c )
gives a 3 x 5 matrix (not 3 x 1 as desired) due to mixing of logical and subscript indices. The logical indices in r pick out rows in A with r==1. Meanwhile row array c picks out elements from each row according to the numeric index:
ans =
3 2 0 3 0
0 2 0 0 0
3 2 4 3 5
What you really want are indices into the rightmost nonzero elements in each row starting with 1. The solution uses linear indices (numeric) to get the correct elements from the matrix.
I think this should do the trick. I wonder if there is more elegant way of doing this though.
% get only rows u want, i.e. with first row == 1
M2 = M(r,:);
% get indices of
% "the rightmost non-zero value of each row in M"
% for the rows u want
indicesOfinterest = c(r==1);
noOfIndeciesOfinterest = numel(indicesOfinterest);
% desired output column vector
output = zeros(noOfIndeciesOfinterest, 1);
% iterate through the indeces and select element in M2
% from each row and column indicated by the indice.
for idx = 1:noOfIndeciesOfinterest
output(idx) = M2(idx, indicesOfinterest(idx));
end
output % it is [3; 2 ; 5]
You can use
arrayfun(#(x) M(x,c(x)), find(r))
But unless you need r and c for other purposes, you can use
arrayfun(#(x) M(x,find(M(x,:),1,'last')), find(M(:,1)==1))
Here is a way to do it using linear indexing:
N = M';
lin_index = (0:size(N,1):prod(size(N))-1) + c;
v = N(lin_index);
v(r)

How can I simplify in Matlab?

I want to simplify the following operation, but it yields me an error that says: too many input arguments. Can anybody tell me what am i doing wrong???
>>
syms a b c d e f g h i j k l x y xy
A=[1 a b a^2 a*b b^2; 1 c d c*2 c*d d^2; 1 e f e^2 e*f f^2; 1 g h g^2 g*h h^2; 1 i j i^2 i*j j^2; 1 k l k^2 k*l l^2]
B=[1; 0; 0; 0; 0; 0]
A =
[ 1, a, b, a^2, a*b, b^2]
[ 1, c, d, 2*c, c*d, d^2]
[ 1, e, f, e^2, e*f, f^2]
[ 1, g, h, g^2, g*h, h^2]
[ 1, i, j, i^2, i*j, j^2]
[ 1, k, l, k^2, k*l, l^2]
B =
1
0
0
0
0
0
>> simplify(inv(A)*B, 'steps', 100)enter code here
I've put the code you pasted in my copy of matlab (R2013a) and it finishes without any errors. The result is not simplified very much though.
If your computer is choking on the computation (it is very long), you could try separating the things a bit and see if it helps.
vec=inv(A)*B
for n=1:6
results(n)=simplify(vec(n), 'steps', 100);
end
results
Your call belongs to this MATLAB function:
But it is in Symbolic Math Toolbox, which means it can only simplify math formulas instead of complex matrix computation.
Simplify Favoring Real Numbers
To force simplify favor real values over complex values, set the value of Criterion to preferReal:
syms x
f = (exp(x + exp(-x*i)/2 - exp(x*i)/2)*i)/2 - (exp(- x - exp(-x*i)/2 + exp(x*i)/2)*i)/2;
simplify(f, 'Criterion','preferReal', 'Steps', 100)
ans =
cos(sin(x))*sinh(x)*i + sin(sin(x))*cosh(x)
If x is a real value, then this form of expression explicitly shows the real and imaginary parts.
Although the result returned by simplify with the default setting for Criterion is shorter, here the complex value is a parameter of the sine function:
simplify(f, 'Steps', 100)
ans =
sin(x*i + sin(x))
Instead, I think you could try use this function:
Simplify(f, Steps = numberOfSteps)
But first of all, you need a 'f' which could be used like a recursion or iteration function.
e.g. Simplify(sin(x)^2 + cos(x)^2, All)
Hope this helps!

Modulo and remainder (Chinese remainder theorem) in MATLAB

How do I find the least possible value in Matlab, given the modulo values and its remainder values in an array? for example:
A=[ 23 90 56 36] %# the modulo values
B=[ 1 3 37 21] %# the remainder values
which leads to the answer 93; which is the least possible value.
EDIT:
Here is my code but it only seems to display the last value of the remainder array as the least value:
z = input('z=');
r = input('r=');
c = 0;
m = max(z);
[x, y] = find(z == m);
r = r(y);
f = find(z);
q = max(f);
p = z(1:q);
n = m * c + r;
if (mod(n, p) == r)
c = c + 1;
end
fprintf('The lowest value is %0.f\n', n)
Okay, so your goal is to find the smallest x that satisfies B(i) = mod(x, A(i)) for each i.
This page contains a very simple (yet thorough) explanation of how to solve your set of equations using the Chinese Remainder Theorem. So, here's an implementation of the described method in MATLAB:
A = [23, 90]; %# Moduli
B = [1, 3]; %# Remainders
%# Find the smallest x that satisfies B(i) = mod(x, A(i)) for each i
AA = meshgrid(A);
assert(~sum(sum(gcd(AA, AA') - diag(A) > 1))) %# Check that moduli are coprime
M = prod(AA' - diag(A - 1));
[G, U, V] = gcd(A, M);
x = mod(sum(B .* M .* V), prod(A))
x =
93
You should note that this algorithm works only for moduli (the values of A) which are coprime!
In your example, they are not, so this will not work for your example (I've put an assert command to break the script if the moduli are not coprime). You should try to implement yourself the full solution for non-comprime moduli!
P.S
Also note that the gcd command uses Euclid's algorithm. If you are required to implement it yourself, this and this might serve you as good references.