Hmm, the numerically unstable part of the calculation lies in division by a difference.
Among real numbers, this is fine unless the line segments are well and truly parallel. Much the same as saying, two random uncorrelated real numbers will *never* be equal, only greater or lesser than; except in circumstances with an explicit mathematical constraint (which is equivalent to specifying that the numbers are equal). In analog circuitry, there is no "equator", only the comparator -- greater or lesser than. (Of course, on the margin near "equal", finite gain and SNR result in a hazy gray area, which could be interpreted as "approximately equal", or as a measure of statistical confidence, "we're not very sure which one is greater".
Floats are a good approximation, and in practice the only exceptions you'll see are contrived cases. In my program, I do observe an error in one cardinal direction, if the position is advanced only in fixed steps (as soon as you, for example, turn and move in another direction, the bits are all wrong and it won't do it anymore -- unless you perform the exact same movements in reverse, which may not even be possible). (The underlying cause is not parallelism, but actually being exactly on the line between regions, and technically being on one region while trying to draw something from the other -- which doesn't exist, so it doesn't draw anything on that one point.)
Other than contrived cases (very particular moves, setups, etc.), I have seen one other instance of this sort of error. I was playing Portal, and trying to move extremely precisely through a portal. I suspect it crashed when I reached the point exactly in the middle, so it couldn't tell which side I was on (either trying to perform all the tasks -- collision, graphics, physics, etc. -- of both rooms, or neither!) and broke.
So, it's worth noting that, even if you do use floats (which I wouldn't recommend for embedded, but the platform is unspecified), although the chances of equality are small, the case still exists, and sooner or later must be handled. I imagine many a random game crash has resulted from exactly this fallacy of ignoring the trichotomy of numbers (lesser than, equal to, or greater than).
All this to say; even if you use floats, you have to watch out for it. You can get away without, but don't whine if you see random, irreproducible errors. The chances are much, much greater if you use smaller floats (i.e., float instead of double), and greater still under some unlucky combinations of integers (a 32 bit int contains as much information as a 32 bit float, but it depends on how you use it; in fixed point, you must always watch out for the dynamic range (how big the integral part can get / needs to be) and precision detail (how small the fractional steps are; how excess bits of products and quotients are handled).
Going back to division by difference: there are some options. The determinant of integers will always be an integer. A singular matrix has a zero determinant, so you can check that as a conditional; a singular matrix also has no inverse. However, the adjoint of a matrix (I'd have to look up what the definition is for a 2x2) is nearly the inverse (there's also a pseudo-inverse, but I forget what and why), and always exists, even of a singular matrix. By avoiding total inversion or division, you can potentially do the calculations in a more stable manner, avoiding division until the last possible step. This also helps retain accuracy and numerical stability, especially when integers or relatively few bits are used. (Obviously, this also goes for digital (hardware) calculations, but the same lessons apply to analog circuits as well -- not that analog computers are all that popular these days.)
Tim