Error with Addition and Subraction of large numbers (e+30)
4 次查看(过去 30 天)
显示 更早的评论
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 个评论
Guillaume
2018-3-22
@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
采纳的回答
John D'Errico
2018-3-21
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 个评论
John D'Errico
2018-3-23
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?
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!