I stumbled over the following strange thing while using matlab's symbolic toolbox
/ >> syms e
/>> y=11111111111111111^e
y =
11111111111111112^e
Seems like there is a limitation when working with large numbers. Can this be solved without changing to a completely different system, like sage?
I think the problem is that Matlab parses the number into a double before it converts it to
a symbolic expression. As a double has a 52-bit mantissa, you have approximately 16 significant digits but your number is longer.
As an alternative, you could try to create the number directly from a string:
y=sym('11111111111111111')^e
Unfortunately, I do not have Matlab available right now, so this answer is untested.
It's not a bug, it's a feature. And it's called "round-off error"
matlab uses a double format to store normal variable, just like the double in C programming language, and many other languages like C++.
Actually, the "bug" has nothing to do with the "^x",as we can see:
>> clear
>> syms y
>> format bank
>> y=11111111111111111
y =
11111111111111112.00
Even a simple assign triggers the "bug".
And we can see how a double variable is really stored in memory in VS, using debug mode:
As you can see in the screenshot, both a and b are stored as "2ea37c58cccccccc" in the memory, which means the computer can't tell one from the other.
And that's the reason of the "bug" you found.
To avoid this, you can use symbolic constant instead:
>> y=sym('11111111111111111')
y =
11111111111111111
In this way, the computer will store the "y" in memory in a different format, which will avoid round-off error and cost more memory.
Related
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
If I make a single precision operation with the values, it will give a result ending with 8:
>> single(single(6.500001e+02)*single(-64.1775131)*single(0.65)*single(2))
ans = -5.4230008e+004
Then I make any operation using double precision, and the same operation as before, using single precision, the result will be different from the first time I run it:
>> double(6.5000012e+02)*double(-64.1775131)*double(0.65)*double(2)
ans = -5.423000858119204e+004
>> single(single(6.500001e+02)*single(-64.1775131)*single(0.65)*single(2))
ans = -5.4230004e+004
This problem happens in Matlab 2008a 32 bits. This is not a problem in Matlab 2012b 64 bits.
Any thoughts on how to avoid this problem?
Thank you.
I could not test but, from what I could find on MATLAB Central, it seems to be a bug in the Global Workspace #versions R2008*. So, to avoid the problem:
Don't execute code from Command Window;
Stick to double precision, unless under severe memory constraints (it's even faster, because default type is double);
Work in functions rather than scripts (apparently the function local Workspace is not affected by this bug)
Use a R2009+ MATLAB release, which seems to have fixed the bug.
I am trying to solve a non-linear system of equations using the Newton-Raphson iterative method, and in order to explore the parameter space of my variables, it is useful to store the previous solutions and use them as my first initial guess so that I stay in the basin of attraction.
I currently save my solutions in a structure array that I store in a .mat file, in about this way:
load('solutions.mat','sol');
str = struct('a',Param1,'b',Param2,'solution',SolutionVector);
sol=[sol;str];
save('solutions.mat','sol');
Now, I do another run, in which I need the above solution for different parameters NewParam1 and NewParam2. If Param1 = NewParam1-deltaParam1, and Param2 = NewParam2 - deltaParam2, then
load('solutions.mat','sol');
index = [sol.a]== NewParam1 - deltaParam1 & [sol.b]== NewParam2 - deltaParam2;
% logical index to find solution from first block
SolutionVector = sol(index).solution;
I sometimes get an error message saying that no such solution exists. The problem lies in the double precisions of my parameters, since 2-1 ~= 1 can happen in Matlab, but I can't seem to find an alternative way to achieve the same result. I have tried changing the numerical parameters to strings in the saving process, but then I ran into problems with logical indexing with strings.
Ideally, I would like to avoid multiplying my parameters by a power of 10 to make them integers as this will make the code quite messy to understand due to the number of parameters. Other than that, any help will be greatly appreciated. Thanks!
You should never use == when comparing double precision numbers in MATLAB. The reason is, as you state in the the question, that some numbers can't be represented precisely using binary numbers the same way 1/3 can't be written precisely using decimal numbers.
What you should do is something like this:
index = abs([sol.a] - (NewParam1 - deltaParam1)) < 1e-10 & ...
abs([sol.b] - (NewParam2 - deltaParam2)) < 1e-10;
I actually recommend not using eps, as it's so small that it might actually fail in some situations. You can however use a smaller number than 1e-10 if you need a very high level of accuracy (but how often do we work with numbers less than 1e-10)?
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)
I am experiencing problems when I compare results from different runs of my Matlab software with the same input. To narrow the problem, I did the following:
save all relevant variables using Matlab's save() method
call a method which calculates something
save all relevant output variables again using save()
Without changing the called method, I did another run with
load the variables saved above and compare with the current input variables using isequal()
call my method again with the current input variables
load the out variables saved above and compare.
I can't believe the comparison in the last "line" detects slight differences. The calculations include single and double precision numbers, the error is in the magnitude of 1e-10 (the output is a double number).
The only possible explanation I could imagine is that either Matlab looses some precision when saving the variables (which I consider very unlikely, I use the default binary Matlab format) or that there are calculations included like a=b+c+d, which can be calculated as a=(b+c)+d or a=b+(c+d) which might lead to numerical differences.
Do you know what might be the reason for the observations described above?
Thanks a lot!
it really seems to be caused by the single/double mix in the calculations. Since I have switched to double precision only, the problem did not occur anymore. Thanks to everybody for your thoughts.
these could be rounding errors. you can find the floating point accuracy of you system like so:
>> eps('single')
ans =
1.1921e-07
On my system this reports 10^-7 which would explain discrepancies of your order
To ensure reproducible results, especially if you are using any random generating functions (either directly or indirectly), you should restore the same state at the beginning of each run:
%# save state (do this once)
defaultStream = RandStream.getDefaultStream;
savedState = defaultStream.State;
save rndStream.mat savedState
%# load state (do this at before each run)
load rndStream.mat savedState
defaultStream = RandStream.getDefaultStream();
defaultStream.State = savedState;