evaluate numeric part of a "sym" variable - matlab

I need to evaluate numeric part of a "sym" variable in MATLAB(something like "evalf" function in maple) for instance I have this sym variable :
(12*(51*EE*II - 8*39^(1/2)*EE*II))/(AA*ll^4*ro)
"evalf" in maple gives me 12.48019224*EE*II/(AA*ll^4*ro), is there any way to do this in MATLAB?

I think that you're looking for the vpa (variable precision arithmetic) function
syms EE II AA ll ro
y = (12*(51*EE*II - 8*39^(1/2)*EE*II))/(AA*ll^4*ro)
vpa(y)
which returns
ans =
(12.48019215375377223869826038978*EE*II)/(AA*ll^4*ro)

MATLAB has a simplify command, but keep in mind that the symbolic toolbox does not like to evaluate to give decimal, it will try to keep everything in fractional values, since that is more accurate anyway.
syms('EE','AA','ll','II','ro')
simplify((12*(51*EE*II - 8*39^(1/2)*EE*II))/(AA*ll^4*ro)))
This will reduce down into the following
-(12*EE*II*(8*39^(1/2) - 51))/(AA*ll^4*ro)
Whether this is more to your liking is really up to you, but I would suggest keeping things in fractions as opposed to decimal. More accuracy is better.
The eval function might also be of some use to you, but that too will keep it fractional. Using that will give you
(13722116389931*EE*II)/(1099511627776*AA*ll^4*ro)

Related

Convert symbolic expression into a rational polynomial

I have a lengthy symbolic expression that involves rational polynomials (basic arithmetic and integer powers). I'd like to simplify it into a single (simple) rational polynomial.
numden does it, but it seems to use some expensive optimization, which probably addresses a more general case. When tried on my example below, it crashed after a few hours--out of memory (32GB).
I believe something more efficient is possible even if I don't have a cpp access to matlab functionality (e.g. children).
Motivation: I have an objective function that involves polynomials. I manually derived it, and I'd like to verify and compare the derivatives: I subtract the two expressions, and the result should vanish.
Currently, my interest in this is academic since practically, I simply substitute some random expression, get zero, and it's enough for me.
I'll try to find the time to play with this as some point, and I'll update here about it, but I posted in case someone finds it interesting and would like to give it a try before that.
To run my function:
x = sym('x', [1 32], 'real')
e = func(x)
The function (and believe it or not, this is just the Jacobian, and I also have the Hessian) can't be pasted here since the text limit is 30K:
https://drive.google.com/open?id=1imOAa4VS87WDkOwAK0NoFCJPTK_2QIRj

Accuracy error in binomials using MATLAB?

The value is absolute integer, not a floating point to be doubted, also, it is not about an overflow since a double value can hold until 2^1024.
fprintf('%f',realmax)
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The problem I am facing in nchoosek function that it doesn't produce exact values
fprintf('%f\n',nchoosek(55,24));
2488589544741302.000000
While it is a percentage error of 2 regarding that binomian(n,m)=binomial(n-1,m)+binomial(n-1,m-1) as follows
fprintf('%f',nchoosek(55-1,24)+nchoosek(55-1,24-1))
2488589544741301.000000
Ps: The exact value is 2488589544741300
this demo shows
What is wrong with MATLAB?
Your understanding of the realmax function is wrong. It's the maximum value which can be stored, but with such large numbers you have a floating point precision error far above 1. The first integer which can not be stored in a double value is 2^53+1, try 2^53==2^53+1 for a simple example.
If the symbolic toolbox is available, the easiest to implement solution is using it:
>> nchoosek(sym(55),sym(24))
ans =
2488589544741300
There is a difference between something that looks like an integer (55) and something that's actually an integer (in terms of variable type).
The way you're calculating it, your values are stored as floating point (which is what realmax is pointing you to - the largest positive floating point number - check intmax('int64') for the largest possible integer value), so you can get floating point errors. An absolute difference of 2 in a large value is not that unexpected - the actual percentage error is tiny.
Plus, you're using %f in your format string - e.g. asking it to display as floating point.
For nchoosek specifically, from the docs, the output is returned as a nonnegative scalar value, of the same type as inputs n and k, or, if they are different types, of the non-double type (you can only have different input types if one is a double).
In Matlab, when you type a number directly into a function input, it generally defaults to a float. You have to force it to be an integer.
Try instead:
fprintf('%d\n',nchoosek(int64(55),int64(24)));
Note: %d not %f, converting both inputs to specifically integer. The output of nchoosek here should be of type int64.
I don't have access to MATLAB, but since you're obviously okay working with Octave I'll post my observations based on that.
If you look at the Octave source code using edit nchoosek or here you'll see that the equation for calculating the binomial coefficient is quite simple:
A = round (prod ((v-k+1:v)./(1:k)));
As you can see, there are k divisions, each with the possibility of introducing some small error. The next line attempts to be helpful and warn you of the possibility of loss of precision:
if (A*2*k*eps >= 0.5)
warning ("nchoosek", "nchoosek: possible loss of precision");
So, if I may slightly modify your final question, what is wrong with Octave? I would say nothing is wrong. The authors obviously knew of the possibility of imprecision and included a check to warn users when that possibility arises. So the function is working as intended. If you require greater precision for your application than the built-in function provides, it looks as though you'll need to code (or find) something that calculates the intermediate results with greater precision.

Is there an inverse factorial expression I can use in Matlab?

I want to edit this to get numberOfCircuits on its own on the left. Is there a possible way to do this in MATLAB?
e1=power(offeredTraffic,numberOfCircuits)/factorial(numberOfCircuits)/sum
The math for this problem is given in https://math.stackexchange.com/questions/61755/is-there-a-way-to-solve-for-an-unknown-in-a-factorial, but it's unclear how to do this with Matlab's functionality.
I'm guessing the easy part is rearranging:
fact_to_invert = power(offeredTraffic,numberOfCircuits)/sum/e1;
Inverting can be done, for instance, by using fzero. First define a continuous factorial based on the gamma function:
fact = #(n) gamma(n+1);
Then use fzero to invert it numerically:
numberOfCircuits_from_inverse = fzero(#(x) fact(x)-fact_to_invert,1);
Of course you should round the result for safe measure, and if it's not an integer then something's wrong.
Note: it's very bad practice (and brings 7 years bad luck) to name a variable with a name which is also a built-in, such as sum in your example.

precision matlab vpa

I'm working with an algorithm, which uses hyperbolic functions and in order to get more accurate results from it I need to increase the precision, so I would like to do it by vpa function means, but I'm not quite sure how to implement it. Here some code to clarify the situation further:
x=18; %the hyperbolic relation is valid until x=18
cosh(x)^2-sinh(x)^2
ans = 1
x=19; %the hyperbolic relation is no longer valid
cosh(x)^2-sinh(x)^2
ans = 0
working with the VPA function:
a=vpa('cosh(40)',30); %the hyperbolic relation is valid beyond x=19
b=vpa('sinh(40)',30);
a^2-b^2
ans = 1.00008392333984375
the problem now is that I don't know how to get the value from VPA with a variable of control 'x'
I tried this but it didn't work:
x=40;
a=vpa('cosh(x)',x,30);
b=vpa('sinh(x)',30);
a^2-b^2
When doing symbolic math or variable precision arithmetic one must be careful with with converting between floating-point. In this case, you need to convert your input, x, to variable precision before passing it in to cosh or sinh (otherwise only the output of these will be converted to variable precision). For your example:
x = vpa(40,30);
a = cosh(x);
b = sinh(x);
a^2-b^2
which returns the expected 1.0. I'm not sure where you found the the use of vpa with string inputs, but that form is no longer used (using strings may even result in different results due to different functions being called). Note also that the default setting for digits in current versions of Matlab is 32.

How to assign values to variables in sym function in matlab while finding out modulus?

While finding out modulus while dealing with very large numbers, i used the sym tool.
Usage of sym tool E.g:
a=5; b=2;
c=sym('a^b');
mod(c,10)
ans= a^b mod 10
The answer should be clearly 5,but it does not pass values to the variables.
The sym tool is very necessary when the inputs are very high i.e a,b,c > 500.
Solution using symbolic toolbox:
a=sym(5)
b=sym(2)
c=sym(10)
mod(a^b,c)
Another possibility that might help you with big numbers:
a=5
b=2
c=10
ar=mod(a,c)
mod(ar^b,c)
This gives the same result, but might reduce the required range drastically.