matlab with symbol, how can I shorten numbers? - matlab

syms w
A=[141432432 23432*w; 31432*w 3543566]
B=[13432*w^2 ; 3424324]
which returns
A =
[ 141432432, 23432*w]
[ 31432*w, 3543566]
B =
13432*w^2
3424324
Then
C=A\B
c1=C(1)
simplify(c1)
returns
C =
-(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641))
(2*(6596791*w^3 - 7567351113687))/(23016082*w^2 - 15661723666641)
c1 =
-(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641))
ans =
-(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641))
I want to simplify c1 to something like this,
c1 = -(w*(3*e^9*w-5.01*e^9))/......
How can I do this? When I do not use syms variables, the numbers looks good. But, if I use this, the formula look so dirty.

It may look "dirty," but that's the point of symbolic math – it's accurate to the full precision of your original input. If you want a result in decimal format you should be aware that it will necessarily be less precise unless the values can be represented exactly as a (sufficiently short) finite decimal expansion. In Matlab's Symbolic Math toolbox, you can simply use the vpa function to convert your result to variable precision arithmetic:
syms w;
c1 = -(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641));
vpa(c1)
which returns
-(1.0*w*(2974823657.0*w - 5014922498.0))/(46032164.0*w^2 - 31323447333282.0)
This doesn't help you much in this case. If you want a lot less precision, as suggested in your question, you can use digits or the second argument to vpa:
syms w;
c1 = -(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641));
vpa(c1,3) % default value is 32
which now returns the much less precise
-(1.0*w*(2.97e9*w - 5.01e9))/(4.6e7*w^2 - 3.13e13)
Lastly, you can also convert your symbolic expression to a floating point function using the unfortunately-named matlabFunction:
syms w;
c1 = -(w*(2974823657*w - 5014922498))/(2*(23016082*w^2 - 15661723666641));
c1_fun = matlabFunction(c1)
which returns the anonymous function
c1_fun =
#(w)-(w.*(w.*2.974823657e9-5.014922498e9))./(w.^2.*4.6032164e7-3.1323447333282e13)

Related

Matlab gives no result when I use the integral function

When trying to calculate the Integral of two variables, I got nothing!
Here is the code:
syms x;
a=0.4;
theta=(9 - 4*x*(5*x - 141/25))^(1/2)/2 - 3/2;
theta_prime=-(40*x - 564/25)/(4*(9 - 4*x*(5*x - 141/25))^(1/2));
g=(1/theta)*theta_prime
s=(1+a*(theta-1))*(g)^2
sgen = int(s,x,0.1,1) %x=0.1:0.1: 1
What was my mistake?
It supposed to be one value, such as '4.86'.
Please advise.
sgen is a symbolic object representing the integral of your function s. You can cast it to double to obtain a numerical value for your integral:
syms x;
a=0.4;
theta=(9 - 4*x*(5*x - 141/25))^(1/2)/2 - 3/2;
theta_prime=-(40*x - 564/25)/(4*(9 - 4*x*(5*x - 141/25))^(1/2));
g=(1/theta)*theta_prime;
s=(1+a*(theta-1))*(g)^2;
sgen = double(int(s,x,0.1,1)) % returns 4.8694
But if you're not interested in the symbolic equation for the integral, there really is no point in using the symbolic toolbox for this. It is much faster to compute the integral numerically. One way to do so is to create a function s(x) and then use integral to find the numerical integration. Do note that s(x) must be vectorized on the x variable for this to work (integral will call it with a vector of x values to save time). For vectorized computation, it is necessary to add dots in front of some of the *, / and ^ operators. This is the result:
a = 0.4;
theta = #(x) (9 - 4*x.*(5*x - 141/25)).^(1/2)/2 - 3/2;
theta_prime = #(x) -(40*x - 564/25)./(4*(9 - 4*x.*(5*x - 141/25)).^(1/2));
g = #(x) (1./theta(x)).*theta_prime(x);
s = #(x) (1+a*(theta(x)-1)).*g(x).^2;
sgen = integral(s,0.1,1.0) % returns 4.8694

How to extract all numeric values from a symbolic expression into a matrix?

I have done partial fraction decomposition to a symbolic polynomial in MATLAB, which gives me a symbolic expression like e.g. the following:
poly = -2i/(x - 1.0 - 1.7i) + 0.57i/(x - 1.0 + 1.1559i)
As you see, this symbolic expression contains both x-variables and constant complex numbers. How can I extract all the numeric values from this expression in MATLAB? The information whether the number is real or complex must not be lost.
So for the given expression poly, how would I get the following matrix A:
A = [-2i, -1-1.7i; .57i, -1+1.1559i]
A =
0 - 2i -1 - 1.7i
0 + 0.57i -1 + 1.1559i
Please also note that A should contain numbers, not symbolic expressions as poly does.
I read of coeffs-function, but it requires the input being a polynomial.
With children-function I am able to divide the summation terms in the symbolic expression to vector of symbolic expressions as shown below:
p = - 0.57735026918962576450914878050196i/(x - 1.0 - 1.7320508075688772935274463415059i) + 0.57735026918962576450914878050196i/(x - 1.0 + 1.7320508075688772935274463415059i);
terms = children(p)
terms =
[ -0.57735026918962576450914878050196i/(x - 1.0 - 1.7320508075688772935274463415059i), 0.57735026918962576450914878050196i/(x - 1.0 + 1.7320508075688772935274463415059i)]
Let me start with that I don't really know what you want to use this for. However, as long as your expressions follow this strict form (i.e. the sum of fractions of the form A/(x+B)), you can hack up a solution to your problem.
I'll be working with your sample input (renamed to pol in order not to shadow the function named poly):
x = sym('x');
pol = -2i/(x - 1.0 - 1.7i) + 0.57i/(x - 1.0 + 1.1559i);
First, cut this into two fractions with children:
fractions = children(pol);
frac1 = fractions(1);
Now, decompose a fraction using numden:
[n,d] = numden(frac1);
A = n;
Now we have terms for a fraction of the form A/(B*x+C), where n == A and d == B*x + C. You can extract the latter two parameters in multiple ways, I prefer calculus:
B = diff(d,x);
C = subs(d,x,0);
Now you know that your first fraction is A/(B*x+C), or if you want you can divide A and C by B to get the "canonical" form of your fraction. Do the same for the second (and further, if any) child of pol.
Check:
>> simplify(frac1 == A/(B*x+C))
ans =
TRUE

How to have MATLAB display answer in decimals with e instead of fractions

So im using MATLAB to calculate the coefficient of an equation and it keeps displaying fractions as the constants instead of decimal form like xxe-x
My code is below
bt = 0.03175;
bpzt = 0.0078;
ht = 0.003;
w = 50; % frequency in Hz
pnic = 8908; % density of nickel
Enic = 200e9; % Young's modulus of nic
L = 0.3048; % Length of canitlever beam in m
syms hn
inertia = (1/12)*bt*ht^3 + (1/2)*bpzt*ht^2*hn - (1/2)*bpzt*ht*hn^2 + (2/3)*bpzt*hn^3
area = (bt*ht - 2*hn*bt + 2*bpzt*hn);
You are using the symbolic math toolbox. You have to convert any symbolic variable back to a numerical one. Use double(area) to get a double value of your symbolic variable area. You can use the function single, too.
But be aware that hn has to get a value first, otherwise it cannot be determined.
Documentation: http://www.mathworks.com/help/symbolic/double.html
To format this output, use the usual Matlab tools. In your case format short e
More details: http://www.mathworks.com/help/matlab/matlab_prog/display-format-for-numeric-values.html
In R2014b, this line:
inertia = (1/12)*bt*ht^3 + (1/2)*bpzt*ht^2*hn - (1/2)*bpzt*ht*hn^2 + (2/3)*bpzt*hn^3
returns
(13*hn^3)/2500 - (863307622649607*hn^2)/73786976294838206464 + (5304162033559185*hn)/151115727451828646838272 + 5527208847278085/77371252455336267181195264
which is a symbolic expression with numeric values represented exactly as rational fractions (even though they may have started out as decimal values in your code). You can convert this using vpa
vpa(inertia)
which returns:
0.0052*hn^3 - 0.000011699999999999999788190263583232*hn^2 + 0.000000035099999999999996664653271376613*hn + 0.000000000071437500000000005341045287673881
The length/precision of the decimal values depends on digits. Displaying this in an exponential-style format (xxe-x) is not an option for any symbolic math expression or value unless you write your own function to parse the string and do the conversion.
To convert this to a vectorized double-precision floating point function, you can use the terribly-named matlabFunction – matlabFunction(inertia) returns:
#(hn)hn.*3.51e-8-hn.^2.*1.17e-5+hn.^3.*5.2e-3+7.143750000000001e-11
But if you're doing this, I'd wonder why you were working with symbolic math in the first place and if it's possible to do everything in much faster double precision.
Keep in mind that if you want to convert to any kind of decimal form, variable precision or floating-point, in many cases you will lose precision. However, if you just want to view the result or perform fourth calculations if double precision, then it should be fine.

Vectorize for loop

The loop is as follows:
for j = 1:20
sigma = (y<0) - (y>=0);
x0 = x;
out_angle = out_angle - sigma*lut(j);
x = x-(y.*sigma)*poweroftwo;
y = y+(x0.*sigma)*poweroftwo;
poweroftwo = poweroftwo/2;
end
out_angle, x,y and sigma are matrices of dim m*n. lut is an array of size 20. poweroftwo is a scalar with initial value 1. Is it possible to vectorize this code and avoid the for loop?
A lot of informaiton is missing for the vectorization of this loop. Just have a look at the line
out_angle = out_angle - sigma*lut(j);
After vectorization you would like to have an expression similar to
out_angle(j) = out_angle(j-1) - sigma*lut(j);
You immediately see that the current out_angle depends on the previously computed value. This also means that out_angle can only be computed sequentially except if you can
come up with an explicit representation of out_angle.
out_angle(j) = out_angle(j-1) - sigma*lut(j)
= out_angle(j-2) - sigma*lut(j-1) - sigma*lut(j)
= out_angle(j-3) - sigma*lut(j-2) - sigma*lut(j-1) - sigma*lut(j)
= ...
= out_angle(0) - sum_{k = 0}^j (sigma*lut(k))
The thing gets more complicated as sigma also depends on j, i.e. actually you have
sigma(j) and thus
out_angle(j) = out_angle(0) - sum_{k = 0}^j (sigma(k)*lut(k))
Unfortunately you also have only an implicit expression for sigma which you have to
resolve in the same manner. You can probably think a bit about the structure behind sigma. This is a variable, which is 1, where y is negative and -1 where y is positive
or zero, i.e. it is something like
sigma = -mySign(y)
where mySign acts like the sign function but gives 1 for a zero argument.
If you can find an explicit representation for sigma, you can insert it into the explicit representation of out_angle above. After that you can (most likely) vectorize the code.

solve In Matlab a quadratic equation with very small coefficients

I'm implementing a code in matlab to solve quadratic equations, using the resolvent formula:
Here´s the code:
clear all
format short
a=1; b=30000000.001; c=1/4;
rdelta=sqrt(b^2-4*a*c);
x1=(-b+rdelta)/(2*a);
x2=(-b-rdelta)/(2*a);
fprintf(' Roots of the polynomial %5.3f x^2 + %5.3f x+%5.3f \n',a,b,c)
fprintf ('x1= %e\n',x1)
fprintf ('x2= %e\n\n',x2)
valor_real_x1= -8.3333e-009;
valor_real_x2= -2.6844e+007;
error_abs_x1 = abs (valor_real_x1-x1);
error_abs_x2 = abs (valor_real_x2-x2);
error_rel_x1 = abs (error_abs_x1/valor_real_x1);
error_rel_x2 = abs (error_abs_x2/valor_real_x2);
fprintf(' absolute_errorx1 = |real value - obtained value| = |%e - %e| = %e \n',valor_real_x1,x1,error_abs_x1)
fprintf(' absolute_errorx2 = |real value - obtained value| = |%e - %e| = %e \n\n',valor_real_x2,x2,error_abs_x2)
fprintf(' relative error_x1 = |absolut error / real value| = |%e / %e| = %e \n',error_abs_x1,valor_real_x1,error_rel_x1 )
fprintf(' relative_error_x2 = |absolut error / real value| = |%e / %e| = %e \n',error_abs_x2,valor_real_x2,error_rel_x2)
The problem I have is that it gives me an exact solution, ie for values ​​a = 1, b = 30000000,001 c = 1/4, the values ​​of the roots are:
Roots of the polynomial 1.000 x^2 + 30000000.001 x+0.250
x1= -9.313226e-009
x2= -3.000000e+007
Knowing that the exact value of the roots of the polynomial are:
x1= -8.3333e-009
x2= -2.6844e+007
Which gives me the following errors in the absolute and relative precision of the calculations:
absolute_errorx1 = |real value - obtained value| = |-8.333300e-009 - -9.313226e-009| = 9.799257e-010
absolute_errorx2 = |real value - obtained value| = |-2.684400e+007 - -3.000000e+007| = 3.156000e+006
relative error_x1 = |absolut error / real value| = |9.799257e-010 / -8.333300e-009| = 1.175916e-001
relative_error_x2 = |absolut error / real value| = |3.156000e+006 / -2.684400e+007| = 1.175682e-001
My question is: Is there an optimum method to obtain the roots of a quadratic equation?, ie I can make changes to my code to reduce the relative error between the expected solution and the resulting solution?
Using the quadratic formula directly in this cases results in a large loss of numerical precision from subtracting two values of very similar magnitude. This is because the expression
sqrt(b*b - 4*a*c)
is nearly the same as b. So you should use only one of these two roots, the one that does not involve subtracting two very close values, and for the other root you can use (for instance) the fact that the product of roots of a quadratic is c/a. I'll let you fill in the gaps.
Why does this sound like a homework problem from a first class in numerical analysis?
It has been a while since I was that young, but as I recall there is a trick. Anyway, you are wrong. The true roots of that polynomial are
solve('x^2 + 30000000.001*x + 0.25')
ans =
-30000000.000999991666666666944442
-0.0000000083333333330555578703796293981491
How well does roots do here?
p = [1 30000000.001 1/4];
format long g
roots(p)
ans =
-30000000.001
-8.33333333305556e-09
That actually seems pretty good. How does HPF do?
DefaultNumberOfDigits 64
a = hpf(1);
b = hpf('30000000.001');
c = hpf('0.25');
r1 = (-b + sqrt(b*b - 4*a*c))/(2*a)
r1 =
-0.000000008333333333055557870379629398149125529835186899898569329967
r2 = (-b - sqrt(b*b - 4*a*c))/(2*a)
r2 =
-30000000.000999991666666666944442129620370601850874470164813100101
Yep, HPF works nicely enough too.
So what happens when you use double precision numbers and the standard formula? Yeah, crapola arrives.
a = 1;
b = 30000000.001;
c = 0.25;
>> r1 = (-b + sqrt(b*b - 4*a*c))/(2*a)
r1 =
-7.45058059692383e-09
>> r2 = (-b - sqrt(b*b - 4*a*c))/(2*a)
r2 =
-30000000.001
Again, massive subtractive cancellation eats away at the result. (I seem to recall that was the problem you had in your last question.)
There is a trick you can use. See that the large solution was well estimated, just not the one near zero. So, what happens if you solved for the roots of fliplr(p) using the quadratic formula? How does this solve your problem? What transformation is implicitly done when you do that? (Sorry, but I won't do your homework. I think the above was enough of a hint anyway.)
i think your "real" values might be wrong (or maybe it's a precision thing... I dunno)
a*(valor_real_x1^2)+b*(valor_real_x1)+c
ans =
9.9999e-07
a*(valor_real_x2^2)+b*(valor_real_x2)+c
ans =
-8.4720e+13
A nice formula for this problem:
var q = sqrt(c*a)/b;
var f = .5 + .5 *sqrt(1-4*q*q);
var x1=-b*f/a;
var x2=-c/(f*b);