Matlab Showing Imaginary Numbers as Real
Show older comments
I'm running a code to solve a thermomechanics problem and the code that solves an equation sometimes output an imaginary and real value. I set up an if statement with the isreal command to weed out the imaginary answers and set a new value to the real part of the solution, and it worked on an example I knew the values for, however it is not working for a solution that the vpa for has an imaginary part. Any thoughts?
syms B
U = 3;
N = 4;
g = 10
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)),B)
if isreal(S(1)) == 1
beta = S(1)
elseif isreal(S(2)) == 1
beta = S(2)
else fprintf("no real beta value")
end
When tested for S(1) specifically I get the following, which highlights my confusion.
>> isreal(S)
ans =
logical
1
>> vpa(S)
ans =
0.2123079473420932527729328757573 - 2.2897391314147019270086132884395i
Accepted Answer
More Answers (2)
syms B
U = 3;
N = 4;
g = 10
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)),B)
whos S
S
isnumeric(S)
The problem is that isreal is not defined to handle a symbolic variable as its input -- an enhancement would be it should warn or the list of classes it responds to to always return false expanded to cover the symbolic object. Whoever designed/wrote it didn't have symbolic variables in mind it appears.
You don't want to test the variable S anyway, you want to test the numeric result.
8 Comments
Luke
on 9 Oct 2024
I don't have and have never used the symbolic TB so I know nothing about its use, but again, "S" is a symbolic object and you need to test the result it has returned, not it directly; that is checking on the class of the object not the values that it contains.
isnumeric(S) returning false merely demonstrates that the value of S is not a numeric result and so it is neither real nor imaginary; it's not the thing you need to be testing. That isreal returns true is not meaningful because isreal is not documented as being valid to be used to test symbolic objects and they are not one of the listed classes that are handled specifically. That may not qualify as an official bug, but it is certainly a quality of implementation oversight. However, the usage is not within documented syntax and so the result as you've learned cannot be relied upon for useful information.
I think you need to do whatever it is to convert the result to numeric, then test that to be imaginary or not instead.
As far as the ultimate goal, it would appear if it is known there always will be a real solution but solve isn't returning one, it needs to be given more help or constraints or you need to find another numeric solution if there aren't features in the symbolic toolbox to require it to return a real result.
Unfortunately, I don't have time to try to learn it at the moment...maybe John D';Errico or one of the other real math/numeric analysts whizards will stumble by...
Goood luck, sorry I don't have a direct solution for you...
Well, it looks like the TB will solve the problem for you directly...
syms B
U = 3;
N = 4;
g = 10;
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)),B,Real=true)
vpa(S,15)
double(S)
Actually, isreal is a method of the sym class
m = methods('sym');
m(strcmp(m,'isreal'))
But it is not documented, so I'm not sure whether it's actually intended to be used.
syms B
U = 3;
N = 4;
g = 10;
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)),B)
Don't know how the sym method isreal works in this case, but it does return the wrong answer.
isreal(S)
But it does work for the vpa form
vpa(S)
isreal(vpa(S))
The documented way to check for realness in the Symbolic toolbox is to use isAlways, which, at least in this case, does seem to work for a root expression.
isAlways(in(S,'real'))
Maybe the isreal(S) case should be reported to tech support?
s=which('-all','isreal');
whos s
s(~contains(s,'built-in'))
And the Symbolic TB version doesn't appear to be exposed...is their a way to confirm which is actually getting called? I went just based on what is returned by doc isreal, of course...
The sym method is called.
syms B
U = 3;
N = 4;
g = 10;
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)),B);
which isreal(S)
I checked which and I guess the sym method doesn't show up on the -all list because it's buried in a file that's not named isreal.m?
dpb
on 10 Oct 2024
I had thought the description in the doc for which
"which ___-all displays the paths to all items on the MATLAB path with the requested name, as well as any files in special folders that have been implicitly added to the path. Such items include methods of instantiated classes."
would have covered the case when the Symbolic TB was available, but obviously it didn't. I don't have it so my only experience is this specific thread...
Walter Roberson
on 9 Oct 2024
Edited: Walter Roberson
on 9 Oct 2024
syms B
U = 3;
N = 4;
g = 10
e = [0 1 2 3];
S =solve(U==N*sum(e.*exp(-B.*e))./sum(exp(-B.*e)), B, 'MaxDegree', 3)
if imag(S(1)) == 0
beta = S(1);
elseif imag(S(2)) == 0
beta = S(2);
elseif imag(S(3)) == 0
beta = S(3);
else
fprintf("no real beta value")
end
disp(char(beta))
5 Comments
Why is MaxDegree applicable here (if not specified, only 1 solution is returned)? According to solve, MaxDegree is only applicable to polynomial equations, which this equation isn't. I realize that solve is converting the equation to a polynomial, so maybe MaxDegree applies there, but that's not what the doc page says (at least not the way I read it).
dpb
on 10 Oct 2024
I didn't follow the purpose of Walter's Answer for this Q?, either...
Walter Roberson
on 10 Oct 2024
Without the MaxDegree, solve() returns log() of a root() structure. With MaxDegree, solve() expands the root() structure to explicit equations.
Walter Roberson
on 10 Oct 2024
It is just a different approach.
Categories
Find more on Symbolic Variables, Expressions, Functions, and Settings in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!