MatLab: Error checking for integers in a row vector - matlab

I have used MatLab to write the following code for Horner's Algorithm
function [answer ] = Simple( a,x )
%Simple takes two arguments that are in order and returns the value of the
%polynomial p(x). Simple is called by typing Simple(a,x)
% a is a row vector
%x is the associated scalar value
n=length(a);
result=a(n);
for j=n-1:-1:1 %for loop working backwards through the vector a
result=x*result+a(j);
end
answer=result;
end
I now need to add an error check to ensure the caller uses integer values in the row vector a.
For previous integer checks I have used
if(n~=floor(n))
error(...
But this was for a single value, I am unsure how to do this check for each of the elements in a.

You've got (at least) two options.
1) Use any:
if (any(n ~= floor(n)))
error('Bummer. At least one wasn''t an integer.')
end
Or even more succinctly...
assert(all(n == floor(n)), 'Bummer. At least one wasn''t an integer.')
2) Use the much more capable validateattributes:
validateattributes(n, {'double'}, {'integer'})
This function can check for more than a dozen other things, too.

Same math will work, but is now checking each element. Try this:
if any(n~=floor(n))
error(...

Related

Matlab "auto-squeeze" plot

Matlab plot requires the data to be of the same dimension. Meaning, you cannot plot a 1x10 vector with a 1x1x10 vector. This is sometimes necessary. For those purposes, you can use the squeeze function to get rid of the singleton dimensions.
However, this is kind of a hassle. For the plot function specifically, it would be useful to have the argument always squeezed. How would one go about creating a new function, lets call it splot which squeezes every input and passes it onto plot. Here is an attempt (that doesn't work)
function splot(varargin)
for i=1:length(varargin)
varargin{i}=squeeze(varargin{i});
end
plot(varargin)
end
plot(varargin) part fails, because that is simply not how matlab syntax works. But is there any way to achieve what I want? I guess I could write a long if elseif chain where I manually write the case with every possible number of input arguments like:
if length(varargin)==2
plot(varargin{1},varargin{2})
if length(varargin)==3
plot(varargin{1},varargin{2},varargin{3})
But this is going to be very annoying. Any better ideas.
This question is similar to Is there any mechanism to auto squeeze in Matlab / Octave , however, not similar enough, because the other question is for squeezing every vector, which is a bad idea. Here I am asking a way to squeeze only the inputs to the plot function and requiring syntax help.
From the docs there are several ways to call plot. Generally
Just numeric arrays, these can be on their own, or one or more pairs
plot(Y), plot(X,Y) or plot(X1,Y1,...,Xn,Yn)
Numeric arrays as before, with a char array giving the line spec
plot(X,Y,LineSpec) or plot(Y,LineSpec)
Either of the previous two, plus name-value pair options
plot(___,Name,Value)
In any of these cases, you want to squeeze the first N inputs which are numeric, since either of the optional additions have the first non-plottable input as a char.
We can achieve that with the following code, see the comments for details:
function h = splot( varargin )
% Check if there are any optional inputs, which will either be
% LineSpec (which is a char) or name-value pairs (which the
% first of will be a char)
bNumericArg = cellfun( #isnumeric, varargin );
% By default, assume all inputs are arrays to plot
lastArrayArg = numel(varargin);
if ~all(bNumericArg)
% In this case, there are some optional inputs, get last array index
lastArrayArg = find( ~bNumericArg, 1 ) - 1;
end
% Squeeze the arrays
for ii = 1:lastArrayArg
varargin{ii} = squeeze(varargin{ii});
end
% Plot with all inputs, optional output
if nargout > 0
h = plot( varargin{:} );
else
plot( varargin{:} );
end
end
There are two possible cases I've not handled here which the plot function can handle,
Having the first input as the target axes i.e. plot(ax,___), could be achieved by altering the loop slightly to start from 1 or 2 depending if the first input is an axes object
Having pairs of arrays each with their own line spec argument i.e. plot(X1,Y1,LineSpec1,...,Xn,Yn,LineSpecn). The later pairs will be ignored. This would be trickier to handle since you'd likely have to parse all inputs and check whether a char is just a line spec or if you're messing with name-value pairs. Maybe a heuristic to do with "two arrays then a char, repeated". I've never used this syntax so omitting the over-complication for now.

Vectorization of function in Matlab

I'm trying to vectorize one function in Matlab, but I have a problem with assigning values.
function [val] = clenshaw(coeffs,x)
b=zeros(1,length(coeffs)+2);
for k=length(coeffs):-1:2
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
end
val=coeffs(1)-b(3)+b(2).*x;
The purpose of this function is to use Clenshaw's algorithm to compute a value of one polynomial with coefficients "coeffs" at point x.
It work fine when x is a single value, but I'd like it to work with vector of arguments too.
When I try to pass a vector I get an error:
Unable to perform assignment because the left
and right sides have a different number of
elements.
Error in clenshaw (line 7)
b(k)=coeffs(k)-b(k+2)+2*b(k+1).*x;
I understand that there is a problem, because I'm trying to assign vector to a scalar variable b(k).
I tried making b a matrix instead of a vector, however I still cannot get the return output I'd like to have which would be a vector of values of this function at points from vector x.
Thank you for helping and sorry if something isn't entirely clear, because English is not my native language.
The vectorized version of your function looks like this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(x),length(coeffs)+2);
for k=length(coeffs):-1:2
b(:,k)=coeffs(k)-b(:,k+2)+2*b(:,k+1).*transpose(x);
end
val=coeffs(1)-b(:,3)+b(:,2).*transpose(x);
end
b needs to be a matrix. In your loop, you have to perform every operation per row of b. So you need to write b(:,k) instead of b(k). Since b(:,k) is a vector and not a scalar, you also have to be careful with the dimensions when using the .* operator. To get the correct results, you need to transpose x. The same goes for the calculation of val. If you don't like the transposition, just swap the rows and cols of b and you get this:
function [val] = clenshaw(coeffs,x)
b=zeros(length(coeffs)+2, length(x));
for k=length(coeffs):-1:2
b(k,:)=coeffs(k)-b(k+2,:)+2*b(k+1,:).*x;
end
val=coeffs(1)-b(3,:)+b(2,:).*x;
end
However, the first version returns a column vector and the second a row vector. So you might need to transpose the result if the vector type is important.

in matlab exit the entire loop and more

I am using this function to get a column vector in which every element is supposed to be 1,
but after n gets large, sometimes some element is not 1, this is due to the method constraint, I want to find out how large is n and return the value. the problem are: 1.it seems that 1 is stored as 1.0000, don't know how to convert it, and how to compare(location in comments) 2. don't know how to exit a loop completely. thank you.
function x = findn(n)
for m = 1:n
[a,b]=Hilbert(m);
m1 = GaussNaive(a,b);
m2 = size(m1,1);
% m1 is a n*1 matrix (a column vector) which every element is supposed
% to be 1, but when n gets large, some element is not 1.
for i = 1:m2
if (m1(i) ~= 1)
% this compare isn't really working, since 1 is stored as 1.0000 for whatever
% for whatever reason and they are not equal or not not equal.
% I doubt whether it really compared.
x = m;
break;
% it just exit the inner for loop, not entirely
end
end
end
In Matlab all numeric variables are, by default, double precision floating-point numbers. (Actually strings and logicals can look like f-p numbers too but forget that for the moment.) So, unless you take steps that your code doesn't show, you are working with f-p numbers. The sort of steps you can take include declaring your variables to have specific types, such as int32 or uint16, and taking care over the arithmetic operations you perform on them. Matlab's attraction to double-precision floating-point is very strong and it's easy to operate on ints (for example) and end up with floating-point numbers again. Start reading about those types in the documentation.
The reasons for avoiding (in-)equality tests on f-p numbers are explained on an almost daily basis here on SO, I won't repeat them, have a look around. The straightforward way to modify your code would be to replace the test with
if (m1(i) ~= 1)
with
if ((abs(m1(i)-1)>tol)
where tol is some small number such that any number larger than 1+tol (or smaller than 1-tol) is to be considered not equal to 1 for your purposes.
Unfortunately, as far as I know, Matlab lacks a statement to break from an inner loop to outside a containing loop. However, in this case, you can probably replace the break with a return which will return control to the function which called your function, or to the command-line if you invoked it from there.

Matlab if loop not working

%function [flag] =verify(area)
[FileName,PathName,FilterIndex]= uigetfile('*.tif','Select the signature file');
display(PathName)
m=[PathName,FileName];
area=nor_area(m);
%display(area)
%area=0.8707;
class(area)
flag=0;
extract=xlsread('D:\Project\Image_processing\important\best.xlsx', 'CW4:CW17');
c=numel(extract);
display(c)
l=extract(1);
class(l)
display(l)
for k = 1:c
%x=extract(k);
if (l==area && flag==0)
% display(extract(k));
flag=1;
display(flag)
end
end
display(flag)
The above is my code for verification, i am not able to compare "l==area", even if the values are same am not able to enter inside the loop. If i try passing the value assume l=0.9999 and the area that i obtain to be the same , if i sent l value explicitly it works..!! but if i try using some function and pass the same value it wont work. I have tried checking the type by using class, both returns double.
Can anyone please help me out with this and if this approach is not good, suggest any alternative that may be used.
It is not generally a good idea to compare floats like you are doing (with the == operator) since floats, unlike integer values are subject to round off. See here and here for a discussion on comparing floats in MATLAB.
Essentially you have to check that two floats are 'close enough' rather than exactly equal, which is what == checks for. MATLAB has a built in function eps for determining the floating point precision on your machine, so use that function when comparing floats. See its documentation for more information.
In most cases it is not wise to compare floating point numbers by a == b. Use abs(a-b)<epsilon where epsilonis some small tolerance like 1e-10 instead.

Concatenate equivalent in MATLAB for a single value

I am trying to use MATLAB in order to generate a variable whose elements are either 0 or 1. I want to define this variable using some kind of concatenation (equivalent of Java string append) so that I can add as many 0's and 1's according to some upper limit.
I can only think of using a for loop to append values to an existing variable. Something like
variable=1;
for i=1:N
if ( i%2==0)
variable = variable.append('0')
else
variable = variable.append('1')
i=i+1;
end
Is there a better way to do this?
In MATLAB, you can almost always avoid a loop by treating arrays in a vectorized way.
The result of pseudo-code you provided can be obtained in a single line as:
variable = mod((1:N),2);
The above line generates a row vector [1,2,...,N] (with the code (1:N), use (1:N)' if you need a column vector) and the mod function (as most MATLAB functions) is applied to each element when it receives an array.
That's not valid Matlab code:
The % indicates the start of a comment, hence introducing a syntax error.
There is no append method (at least not for arrays).
Theres no need to increment the index in a for loop.
Aside of that it's a bad idea to have Matlab "grow" variables, as memory needs to be reallocated at each time, slowing it down considerably. The correct approach is:
variable=zeros(N,1);
for i=1:N
variable(i)=mod(i,2);
end
If you really do want to grow variables (some times it is inevitable) you can use this:
variable=[variable;1];
Use ; for appending rows, use , for appending columns (does the same as vertcat and horzcat). Use cat if you have more than 2 dimensions in your array.