Error with Addition and Subraction of large numbers (e+30)

4 Ansichten (letzte 30 Tage)
Ash Ash
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
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
Ash Ash
Ash Ash am 23 Mär. 2018
I see, thanks for the explanation!

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

John D'Errico
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
Ash Ash
Ash Ash am 23 Mär. 2018
Bearbeitet: Ash Ash am 23 Mär. 2018
I see, thanks for the explanation once again.
John, somehow I am getting this error after downloading the latest version of HPF
hpf('1')
ans =
Error using -
Integers can only be combined with integers of the same class, or scalar doubles.
Error in hpf/disp (line 1426)
F = roundn(F,F.Exponent - F.NumberOfDigits(1));
Error in hpf/display (line 1505)
disp(F)
========
X = hpf(1.2345678901234567890123456789012)
X =
Error using -
Integers can only be combined with integers of the same class, or scalar doubles.
Error in hpf/disp (line 1426)
F = roundn(F,F.Exponent - F.NumberOfDigits(1));
Error in hpf/display (line 1505)
disp(F)
John D'Errico
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?

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

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!

Translated by