How to get around round off error?

Hello all, I read about the round off error that MATLAB experiences with double precision numbers, and it being caused by how MATLAB stores numbers in binary. I was wondering if there was any way to get around this. Specifically I would like to subtract 0.021557700000000 from 0.021557800000000 without any round off error. The answer should be 1e-7 but MATLAB gives -9.999999999940612e-08. I tried to convert the numbers to symbols and subtract symbolically but I got the same error. Any ideas?

11 comentarios

Guillaume
Guillaume el 8 de Jul. de 2019
The answer should be 1e-7
Well, for a start, 1e-7 cannot be stored exactly on any computer that uses ieee double representation.
The answer is 1e-7 for all intent and purposes. It only differs by about 6e-19 which is just noise compared to 1e-7.
The fact that you write 0.02155770000000 instead of 0.0215577 would indicate that you missed the point of what you were reading. You will always get roundoff error on a computer but unless you run into issues such as catastrophic cancellation, that roundoff error is negligible.
Indeed, the only way to avoid any kind of roundoff is to go the symbolic way, which is orders of magnitude slower, and completely overkill in most situations. Of course, if you convert from symbolic back to numerical, you'll go back to having roundoff.
Rather than trying to eliminate roundoff, just accept that it's there. It's also present in the physical world.
I understand that the roundoff is incredibly small and doesn't matter. The problem is that I am doing a grid convergence study, and I have 3 numbers for the high, medium, and low precision computations. The numbers are 0.0215579 for high, 0.0215578 for medium, and 0.0215577 for low. Whenever I run this through my function I get error on the order of 6000 percent. The error calculation subtracts the medium from the high, and the low from the medium. Since the two calculations should be equal the grid convergence error should be zero, but since the subtractions dont result in the same number, the error is huge. I am just looking for a way to get around this issue. I have tried doing this symbolically because the increase in computation time doesnt really matter, but I still get the same error when I do it symbolically. Here is what I wrote. Thank you for your help.
A=sym(.0215577);
B=sym(.0215578);
Result=A-B
Walter Roberson
Walter Roberson el 8 de Jul. de 2019
sym('.0215577','d')
Will get you a bit closer, but it turns out that symbolic floating point is not really stored internally as decimal, the internal base appears to be 2^30. This is mostly not noticeable but differences against decimal representation can be found if you push the system hard enough.
Yeah, I did get this to show more decimals but it seems that .021577 and all the other numbers cannot be stored at an exact value like this. They become 0.021557699999999999085353863392811 or something along those lines. I noticed that if I run the script below, the eps is the same. I was wondering, if two numbers would be close enough would their eps be the same because I found that in this exact case it works?
A=(215577/10000000);
B=(215578/10000000);
C=(215579/10000000);
BA=B-A;
CB=C-B;
BA_eps=eps(BA)
CB_eps=eps(CB)
if BA_eps == CB_eps
B=C;
A=C;
end
In this case C is supposed to be the most precise solution so that is why I set them all to C. Is there a second condition that I should put on that if statement so that it doesnt enter it when it isnt supposed to? Also is this a right way of getting around this?
Sorry, I should have said
sym('.0215577')
This is not the same as
sym(.0215577)
or
sym(.0215577,'d')
ARSHA MAMOOZADEH
ARSHA MAMOOZADEH el 8 de Jul. de 2019
Editada: ARSHA MAMOOZADEH el 8 de Jul. de 2019
I got the first one to work, but how would I do that with variables instead since I am outputting the values to a function. For example...
F1=.0215577
F2=.0215578
A=sym('F1')
B=sym('F2')
Result=A-B
This just ends up printing "F1-F2" instead of a numerical result.
F1=.0215577
You already have roundoff error at this point. The number .0215577 cannot be stored exactly. The actual number that is stored is 2.155769999999999908535386339281103573739528656005859375e-2
ARSHA MAMOOZADEH
ARSHA MAMOOZADEH el 8 de Jul. de 2019
My bad, thank you for your help.
Right.
If you know the number of decimal places involved then you can do something like
round(F1*1e7) - round(F2*1e7)
and the answer would then be 1e7 times too large. However, you cannot just divide through by 1e7 without introducing round-off error.
Yep. Currently I am testing this out...
A=(215577/10000000);
B=(215578/10000000);
C=(215579/10000000);
BA=B-A;
CB=C-B;
BA_eps=eps(BA)
CB_eps=eps(CB)
if BA_eps == CB_eps
B=C;
A=C;
end
This seems to be working, and I think I am going to add a tolerance on the if statement. Another thing I made was this however it still has the round off error.
F21=round(F2-F1,16)
F32=round(F3,F2,16)
16 is the maximum number of decimals my input has.
Stephen23
Stephen23 el 8 de Abr. de 2021
"16 is the maximum number of decimals my input has."
Then any attempt to define a higher precision number for your operations is totally meaningless.
I very much doubt that your input data were even measured to 16 significant digit accuracy, given that some of the most accurate measurements in science are around the same order:

Iniciar sesión para comentar.

Respuestas (1)

Zakaria moeri
Zakaria moeri el 8 de Abr. de 2021

0 votos

take a look at vpa and digits method already exist in matlab documentation.

Categorías

Preguntada:

el 8 de Jul. de 2019

Comentada:

el 8 de Abr. de 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by