Error with Addition and Subraction of large numbers (e+30)
4 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Ash Ash
am 21 Mär. 2018
Kommentiert: John D'Errico
am 23 Mär. 2018
Hi all Good People of MATLAB
I am facing a problem and I require your help and expertise:
When I perform this computation:
>> 5.357777e30+5.367777e30-5.357777e30-5.367777e30
ans =
-1.125899906842624e+15
I do not get 0 as I would expect. I was expecting the error for double precision computation to be around 10e-15 to 10e-16 , but apparently representing values in this format (Ae+30) brings up this error.
Would you please help me on what I can do to solve this problem? Is there a way to circumvent this problem and bring the error back to the expected range for double precision without having to resort to vpa() (I am performing the addition and subtraction operations through accumarray() ) or proprietary software like Advanpix?
Or would vpa() be a simple and straightforward solution to this problem? .
Note: The inputs for my computation are not in exponential form "Ae+B" but in double format. However, after several steps of computation, MATLAB automatically converts the values to exponential form when it stores the data into a matrix/variable.
I am facing this problem when I run a matrix of such large numbers through accumarray(), that occurs while I am trying to find the inverse of a 5-dimensional multivector and I am calling the simplifyResult() function from Gerardo Aragon-Camarasa's Clifford Algebra toolbox.
Thank you very much for your help and time.
4 Kommentare
Guillaume
am 22 Mär. 2018
@Ash Ash, "Note: The inputs for my computation are not in exponential form "Ae+B" but in double format. However, after several steps of computation, MATLAB automatically converts the values to exponential form when it stores the data into a matrix/variable".
matlab does not automatically convert anything, and the way matlab displays the number, in exponential form or otherwise, has no impact whatsoever on how the number is stored in memory and hence never has any impact on the result of any calculation.
Furthermore, regardless of how you enter the number, a double (or single) number is always stored in what you'd probably call an exponential form, in terms of powers of 2. You probably would benefit in learning how double numbers are actually stored in memory.
E.g, the integer 3 is actually stored as
sign: 0
fraction: 2^51
exponent: 1024
which is decoded as
(-1)^sign * (1 + fraction/2^52) * 2^(exponent-1023)
= (-1)^0 * (1 + 0.5) * 2^1
= 1 * 1.5 * 2
Akzeptierte Antwort
John D'Errico
am 21 Mär. 2018
Sorry. You can't do it with a double.
This is a problem known as massive subtractive cancellation. It stems from the fact that a double carries roughly 16 digits in the mantissa. Suppose I try to form the number
x = 1 + 1.001002e-13;
sprintf('%0.55f',x)
ans =
'1.0000000000001001421168211891199462115764617919921875000'
It really does not matter if the numbers are REALLY large. What matters is what happens in the least significant bits of that number. So if they are all on the order of 1e30, it is the same as if they are all on the order of 1.
So we lost some precision in those TINY bits.
x - 1
ans =
1.0014e-13
So instead of x-1 being 1.002e-13, the result is not exactly what we want.
The problem arises whenever we subtract two numbers that are very nearly identical, except for their least significant bits.
So, no, you cannot solve the problem using a double.
Worse, you may not even be able to solve it using VPA, UNLESS you are very careful in creating the numbers.
x = sym(1 + 1.0001002e-13)
x =
2251799813685473/2251799813685248
vpa(x-1)
ans =
0.000000000000099920072216264088638126850128174
So vpa got it wrong too! Just throwing vpa at the problem is NOT sufficient.
Suppose I am a bit more careful?
x = sym(1) + 1.0001002e-13
x =
79228162514272261203661565163/79228162514264337593543950336
vpa(x-1)
ans =
0.0000000000001000100200000000039377780293699
So I might have tried this:
x = sym('1 + 1.0001002e-13')
Warning: Support of character vectors will be removed in a future release. Character vectors can be used only for variable names and numbers. Instead, to create symbolic
expressions first create symbolic variables using 'syms'. To evaluate character vectors and strings representing symbolic expressions, use 'str2sym'.
> In sym>convertExpression (line 1581)
In sym>convertChar (line 1486)
In sym>tomupad (line 1236)
In sym (line 215)
x =
1.00000000000010001002
vpa(x-1)
ans =
0.00000000000010001001999999999999999999998018
Getting better, except for that irritating warning.
x = 1 + sym('1.0001002e-13')
x =
1.00000000000010001002
vpa(x-1)
ans =
0.00000000000010001001999999999999999999998018
The point is, just throwing vpa at a problem does not always fix it.
I suppose you could use my HPF toolbox too. But even there you need to be careful.
x = hpf(1 + 1.002e-13,50)
x =
1.0000000000001001421168211891199462115764617919922
x-1
ans =
0.00000000000010014211682118911994621157646179199218750000000000
So that got it wrong. But if I create the number in a way that maintains full precision, it works too.
x = hpf('1.002e-13',50) + 1
x =
1.0000000000001002
x - 1
ans =
0.0000000000001002
The point is, you need to understand how numbers are stored in a floating point format, if you are to effectively do computations like this.
11 Kommentare
John D'Errico
am 23 Mär. 2018
Huh? How did you install it? None of this makes any sense, unless you did something strange with your search path.
Or, do you have a really old version of MATLAB? It was built in R2012a, at least from what the web page says. I cannot recall when I wrote it. Are you using an older release than that?
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Characters and Strings finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!