Practically Accurate Floating-Point Math
computer.org
computer.org
Another way to do the same type of error analysis of numerical algorithms is to use a parameter sensitivity library. In the end, numerical stability can be thought of as the sensitivity of the final answer to separate independent changes in each intermediate value obtained in the computation of the answer. This is sometimes overlooked, I think, and it's quite easy to implement as well.
I have one quibble. They say "Use (x-y)(x+y) instead of x^2-y^2". This is true, but (in my opinion) misleading: the function (x,y) -> x^2-y^2 is itself ill-conditioned when x is near y, and using a more numerically stable algorithm to evaluate an ill-conditioned function will not improve the function's condition. If x and y are close to each other, the inaccuracy introduced by using x^2-y^2 is close to the inaccuracy due to using approximate values for x and y. So it you have x^2-y^2, I think the first thing you should worry about is whether your computation is ill-conditioned, and only then worry whether it's numerically stable. I say this because I sometimes see people try to evaluate x^2-1, notice it is inaccurate for x near 1, and try to replace x^2-1 with (x-1)*(x+1), which is still inaccurate.
If you are used to working with complex computations (most of what is usually referred to as numerical analysis, for example), you likely do not find yourself in the latter situation very often. However, for those of us who work on low-level details of floating-point on a regular basis, the latter analysis is often critical.
OK, but how does one apply this advice in practice?
The radiative exchange between two surfaces goes as x^4-y^4 where x and y are the surface temperatures. I can worry about whether that's ill-conditioned all I want, but at the end of the day I'm further ahead evaluating (x-y)(x+y)(x^2+y^2) than the original expression.
Similarly, if I need to find x^2-1, what recourse do I have? Maybe there's some reduction that makes the computation more stable. But normally I would expect to discover such a reduction by turning x^2-1 into (x-1)(x+1), and then seeing if one of those factors cancels out somewhere. So it still seems like a good first step.
Anyway, in real job as a dev, when I made a moving average it was the most impressive math I done, and when I was resorting to ifft (convolution with a hammer function) I was told it should not be used because it was unmaintainable because no one understood.
I have been so ... hammered down by computer engineer so sure of themselves that I learnt to shut my mouth to keep my job.
Who really read this?
I love it, but I never did any serious brainy stuff as a dev.
This article first appeared in "Computing in Science and Engineering" magazine, so its audience is mainly scientists in various fields who use floating point in their research. Because of that breadth, I tried to make it as accessible as possible, while teaching enough floating-point principles to make debugging make sense.
I honestly hope that everyone who uses floating point reads this.
I went in university to learn physics, so I have my geometry and numerical analysis basic understanding.
I honestly thinks people who learnt it has a cursus for graduating did not care, and that they actually don't understand their difficulties even though they learnt about it. They don't see it is a float.
One of the other misconception I have to fight with is what is time.
CS engineer believe in a perfect synchronized time and timestamp that are monotonicly growing the same everywhere with a 10-9 precision and rely on that for distributed systems. My guts (and general relativity too I guess) are telling me they are wrong.
But since I am stuck reimplementing a bubble sort for phone numbers I don't quite have the time to work on it. I have to live with my tingling intuitions telling me I am either an overpessimistic ass being a pain for my colleague that is becoming obsolete by lack of studying, or the whole industry seems getting more magic oriented than science oriented.
Anyway, like a lot of people I am getting inadapted out there.
At least, I have spare time to work on game of life and complex systems... sometimes, and I have a lovely caring wife, so I am happy either way :)
Another correct test case is as follows:
> (rat (float -1 23 -6))
- (26) / (34)
In truth, this should be - 23 / 64, which is a very different number. Perhaps there's comical value in an article about accurate math having inaccurate typography?It's amazing how much you miss when you think you already know what's written.
I feel that there is a lot of overlap between cases where you may want to minimize error while at the same time still be performant (simulations, ray tracing, rendering, etc.). So you're left with a situation where you end up minimizing error, but still being slow.
Support for subnormals can easily be disabled (usually be enabling "Flush to Zero" behavior) to allow for better performance on essentially all recent hardware.
Over the last few years, subnormal stalls have shrunk rapidly, and gone away entirely in some cases. Intel started this process with the Sandybridge architecture. These stalls are also greatly reduced in some arm64 implementations.
I don't know the status of AMD's floating point at the moment, but I hope they're doing something about that.
Edit: It's me. It's just a font with sloping serifs, which is what confused me.
Edit: Never mind, it copies/pastes correctly. The font is just different from what I'm used to.
This uses the Lisp ratio type in place of floats, to avoid the usual float issues.
ntoronto, any thoughts?
Just looking at the Wu-Decimal page, though, I can't tell whether they're internally exact rationals or base-10 floats. If they're base-10 floats, they have all the same issues base-2 floats have. If they're internally exact rationals, I wonder what they do for division, which the set D isn't closed under.
My favorite representation so far pairs a signed float in [2^-512,2^512) with a signed integer to extend the exponent range. The idea is to avoid overflow and underflow, particularly when multiplying thousands of probabilities.
(On average, adding a few thousand log probabilities or densities and then exponentiating the sum yields a number with about 9 digits precision. Worst case for adding log probabilities and exponentiating is about 8 digits precision, and for adding log densities it's 0 digits. Multiplying the same number of probabilities or densities retains about 13 digits in the worst case.)
Nitpick: although base 10 floats have similar issues related to being of limited precision, they are superior to base 2 floats in the aspect of representing decimal numbers without the binary approximation: e.g. 1/10 is nonrepeating as 1.0 x 10^-1 but infinitely repeating as binary, so for IEEE 754 binary32 you get 1.10011001100110011001101 (1.60000002384185791015625) x 2^-4.