[Haskell-cafe] Working around floating-point inaccuracies
Joachim Durchholz
jo at durchholz.org
Sun Aug 5 12:52:52 UTC 2018
Am 05.08.2018 um 14:30 schrieb Michail Pevnev:
> The general pattern to these failures is that one of the coordinates of
> the origin point of the untranslated plane is huge compared to the other
> two - by 4-6 orders of magnitude, while the translation vector is not
> particularly big and has about the same magnitude as the two smaller
> coordinates.
I haven't checked whether this is really the case, but such failures
tend to happen when the math is "badly conditioned" - i.e. if you're
doing the equivalent of a/(b-c) somewhere, where b and c are so close to
each other that most or all significant digits cancel out.
Geometrically, a typical task would be trying to find the intersection
of almost-parallel linear objects.
Either your test code has the same instabilities as the tested code. In
this case, your tested code isn't suitable for certain classes of
situations; you'll want to find out which these are, and document them.
Or try and find a different algorithm.
In this case: Congratulations, testing revealed a real problem in your
code :-)
Or your test code has different instabilities. In that case, rewrite
your test code.
A different way to phrase this is: Your test code makes different
assumptions (about numeric stability, that is) than the code under test.
The *clean* way to deal with this is to calculate the error bounds,
document them, and write test code that checks whether the code under
test is behaving within the calculated error bounds.
However, this is a pretty hairy thing to do; expect to spend several
weeks to get the math worked out - or a few days with a numerics expert
who already has seen it all.
So maybe you'll want to think about alternatives; which of these are
relevant depends a lot on what you're using your code for, and what
kinds of qualities you want to achieve.
Yet another approach might be using Rational instead of float.
Rational is a net win only if you don't have iterations in your code,
otherwise your numerators and denominators will grow on each iteration,
eating up your memory.
Regards,
Jo
More information about the Haskell-Cafe
mailing list