Square root of type int32 variable - matlab

I tried to calculate the square root of a type int32 variable using the sqrt() function, but I got this error: Undefined function 'sqrt' for input arguments of
type 'int32'. Then I found that there's a function called isqrt() that calculates the square root of type integer variables but it doesn't exist in my Matlab version (R2013a). I tried to download this function but I can't find it. I tried powering the value to (1/2) but integers can only be raised to positive integral powers.
So is there any way to do this?

You could write your own isqrt using an anonymous function:
%// variable
A = int32(16)
%// helper function
isqrt = #(x) int32(sqrt(double(x)))
%// root
iroot = isqrt(A)
This function should just used as that, if you're sure that it actually possible to calculate the root, as casting a decimal value to int32(...) will round it, without displaying an error.
So to make it a little more robust, you could create a function like:
function iroot = isqrt(integer)
root = sqrt(double(integer));
if mod(root,1) == 0
iroot = int32( root );
else
disp('Input has no integer root')
end
end

Here is a solution that avoids rounding that happens when you convert from double to an integer type by using fix and also it supports any integer type by using cast and class functions:
isqrt = #(x) cast(fix(sqrt(double(x))), class(x));
So for example:
>> isqrt(int32(15))
ans =
3
However
>> int32(sqrt(double(int32(15))))
ans =
4
Use fix instead of floor to handle negative values correctly:
>> isqrt(int8(-15))
ans =
0 + 3i

Related

How can we put element of vector to symsum?

I am trying to use symsum using Matlab. But I get a strange error.
I am trying to put elements of a vector into symsum:
a=[1,2,3,40,51,61];
syms u n
S1(u) = symsum((a(n+1)*(-u)^n)/factorial(n),n,[0,6])
Error is:
Invalid indexing or function definition. When defining a function, ensure that the arguments are symbolic variables and the body of the function is a SYM expression. When indexing, the input must be numeric, logical, or ':'.
First, I can see a mistake where you write a(n+1), for n going from 0 to 6. When n equals 6, you will have a(7) which doesn't exist. a only has 6 elements.
Then, you have another problem because you are indexing a with a symbol, and symbolic indexing is not allowed (see this post).
Does n really need to be a symbol and do you really need to use symsum? If not, you can try:
a = [1,2,3,40,51,61];
n = 0:5;
syms u
S1(u) = sum( sym( (a(n+1).*(-u).^n)./factorial(n) ) )
This returns:
S1(u) =
- (61*u^5)/120 + (17*u^4)/8 - (20*u^3)/3 + (3*u^2)/2 - 2*u + 1

using 'solve' on vector valued function

I have a vector-valued function defined like this:
eqns =#(z) [0.2178*z(7) + 1.96*sin(z(1)) == -0.2*z(9)*cos(z(1)),...
0.7*z(9) + 1.5*z(4) + 0.2*z(7)*cos(z(1)) - 0.2*z(2).^2*sin(z(1)) == z(5)]
This is a set of two equations where I want z(7) and z(9) to become the subject of the formulae. That is to say, I want these two equations in the form z(7) = f1(z(1),z(2),z(3),z(4),z(5)) and z(9) = f2(z(1),z(2),z(3),z(4),z(5)).
I tried to do this:
[f1,f2]= solve(eqns,z(7),z(9))
but it gives me the error "Undefined function 'z' for input arguments of type
'double'."
Any help will be much appreiated
Without a declaration of z as a symbolic variable, Matlab doesn't know what z is when it tries to evaluate z(7) and z(9) in the call to solve. Therefore, z must be defined prior to the call and also the definition of eqns. Further, since you are treating z as a vector, it is easiest to declare it using sym rather than syms:
z = sym('z',[9,1]);
Lastly, as mentioned in the comments, the first input to solve is to be "specified as a symbolic expression or symbolic equation", so do not declare eqns to be an anonymous, vector-valued function as you would do, for example, fsolve; simply define it using Symbolic Variables, and it will be a Symbolic Expression by construction.
All that said, this code produces an answer for me:
z = sym('z',[9,1]);
z([1,2,4,5]) = sym(rand(4,1));
eqns = [0.2178*z(7) + 1.96*sin(z(1)) == -0.2*z(9)*cos(z(1)),...
0.7*z(9) + 1.5*z(4) + 0.2*z(7)*cos(z(1)) - 0.2*z(2).^2*sin(z(1)) == z(5)];
[f1,f2]= solve(eqns,z(7),z(9));

Matlab nchoosek got difference answer using int64 and sym

This is a question about the function nchoosek in Matlab.
I want to find nchoosek(54,25), which is the same as 54C25. Since the answer is about 10^15, I originally use int64. However the answer is wrong with respect to the symbolic one.
Input:
nchoosek(int64(54),int64(25))
nchoosek(sym(54),sym(25))
Output:
1683191473897753
1683191473897752
You can see that they differ by one. This is not really an urgent problem since I now use sym. However can someone tell me why this happens?
EDIT:
I am using R2013a.
I take a look at the nchoosek.m, and find that if the input are in int64, the code can be simplified into
function c = nchoosek2(v,k)
n = v; % rename v to be n. the algorithm is more readable this way.
classOut = 'int64';
nd = double(n);
kd = double(k);
nums = (nd-kd+1):nd;
dens = 1:kd;
nums = nums./dens; %%
c = round(prod(nums));
c = cast(c,classOut);
end
However, the outcome of int64(prod(nums./dens)) is different from prod(sym(nums)./sym(dens)) for me. Is this the same for everyone?
I don't have this problem on R2014a:
Numeric
>> n = int64(54);
>> k = int64(25);
>> nchoosek(n,k)
ans =
1683191473897752 % class(ans) == int64
Symbolic
>> nn = sym(n);
>> kk = sym(k);
>> nchoosek(nn,kk)
ans =
1683191473897752 % class(ans) == sym
% N!/((N-K)! K!)
>> factorial(nn) / (factorial(nn-kk) * factorial(kk))
ans =
1683191473897752 % class(ans) == sym
If you check the source code of the function edit nchoosek.m, you'll see it specifically handles the case of 64-bit integers using a separate algorithm. I won't reproduce the code here, but here are the highlights:
function c = nchoosek(v,k)
...
if int64type
% For 64-bit integers, use an algorithm that avoids
% converting to doubles
c = binCoef(n,k,classOut);
else
% Do the computation in doubles.
...
end
....
end
function c = binCoef(n,k,classOut)
% For integers, compute N!/((N-K)! K!) using prime factor cancellations
...
end
In 2013a this can be reproduced...
There is as #Amro shows a special case in nchoosek for classOut of int64 or unit64,
however in 2013a this is only applied when the answer is between
flintmax (with no argument) and
double(intmax(classOut)) + 2*eps(double(intmax(classOut)))
which for int64 gives 9007199254740992 & 9223372036854775808, which the solution does not lie between...
If the solution had fallen between these values it would be recalculated using the subfunction binCoef
for which the help states: For integers, compute N!/((N-K)! M!) using prime factor cancellations
The binCoef function would have produced the right answer for the given int64 inputs
In 2013a with these inputs binCoef is not called
Instead the "default" pascals triangle method is used in which:
Inputs are cast to double
The product of the vector ((n-k+1):n)./(1:k) is taken
this vector contains k double representations of fractions.
So what we have is almost certainly floating point error.
What can be done?
Two options I can see;
Make your own function based on the code in binCoef,
Modify nchoosek and remove && c >= flintmax from line 81
Removing this expression will force Matlab to use the more accurate integer based calculation for inputs of int64 and uint64 for any values within their precision. This will be slightly slower but will avoid floating point errors, which are rightfully unexpected when working with integer types.
Option one - should be fairly straight forward...
Option two - I recommend keeping an unchanged backup of the original function, or makeing a copy of the function with the modification and use that instead.

Evaluate Matlab symbolic function

I have a problem with symbolic functions. I am creating function of my own whose first argument is a string. Then I am converting that string to symbolic function:
f = syms(func)
Lets say my string is sin(x). So now I want to calculate it using subs.
a = subs(f, 1)
The result is sin(1) instead of number.
For 0 it works and calculates correctly. What should I do to get the actual result, not only sin(1) or sin(2), etc.?
You can use also use eval() to evaluate the function that you get by subs() function
f=sin(x);
a=eval(subs(f,1));
disp(a);
a =
0.8415
syms x
f = sin(x) ;
then if you want to assign a value to x , e.g. pi/2 you can do the following:
subs(f,x,pi/2)
ans =
1
You can evaluate functions efficiently by using matlabFunction.
syms s t
x =[ 2 - 5*t - 2*s, 9*s + 12*t - 5, 7*s + 2*t - 1];
x=matlabFunction(x);
then you can type x in the command window and make sure that the following appears:
x
x =
#(s,t)[s.*-2.0-t.*5.0+2.0,s.*9.0+t.*1.2e1-5.0,s.*7.0+t.*2.0-1.0]
you can see that your function is now defined by s and t. You can call this function by writing x(1,2) where s=1 and t=1. It should generate a value for you.
Here are some things to consider: I don't know which is more accurate between this method and subs. The precision of different methods can vary. I don't know which would run faster if you were trying to generate enormous matrices. If you are not doing serious research or coding for speed then these things probably do not matter.

fminsearch with vector inputs

I want to minimize this function:
function [GCV2]=GCV(y,x,k)
[n, p]=size(x);
A=(x'*x+k*eye(p));
A=A\x';
A=x*A;
I_mat=eye(n);
num2=(I_mat-A);
num2=num2*y;
num2=norm(num2);
num2=num2^2;
num2=num2/n;
%(norm((I_mat-A)*y)^2)/n;
den2=(I_mat-A);
den2=trace(den2);
den2=den2/n;
den2=den2^2;
GCV2=num2/den2;
end
The x and y values are 13-by-4) and 13-by-1 arrays, respectively, and these values are already defined in the Matlab workspace. I want to optimize on the k value so that the function value GCV is minimized.
The parameter being optimized as well as the output are scalar so fminsearch should be appropriate.
But I can't get it to run?
I've tried several methods, the latest being:
k_min = fminsearch(#GCV,(x;y;0));
??? k_min = fminsearch(#GCV,(x;y;0));
|
Error: Unbalanced or unexpected parenthesis or bracket.
What am I doing wrong?
Looks like you're learning about anonymous functions. fminsearch minimizes a single variable (which may be a vector). Your objective function must therefore have only one input. You have a function, GCV, that takes three inputs. Two are static and are defined in the workspace outside of the minimization, while k is the one to be minimized. To create a function with one input from GCV, you can use any anonymous function, taking care to specify which variables are parameters:
x = ...
y = ...
k0 = 0;
k_min = fminsearch(#(k)GCV(y,x,k),k0);
The second input to fminsearch is the starting parameter (i.e. k0), so specify a starting value of k. Then you can define an anonymous helper function and optimize on that:
>> % define x,y
>> GCVk = #(k) GCV(y,x,k);
>> k0 = 0;
>> k_min = fminsearch(GCVk,k0)
There is probably another way to do this, but this is one of the listed ways of passing additional parameters for the optimizer.
And since there are no bonus points for being first, how about humor. Let's have an example:
>> x=1; y=1;
>> GCVk = #(k) x+y+k; k0=0;
>> k_min = fminsearch(GCVk,k0)
Exiting: Maximum number of function evaluations has been exceeded
- increase MaxFunEvals option.
Current function value: -316912650057057490000000000.000000
k_min =
-3.1691e+26
Found it - the lowest number (minus 2) in the world! Profit?