On 09/10/12 11:32, Oscar Benjamin wrote:
The main purpose of quiet NaNs is to propagate through computation ruining everything they touch. In a programming language like C that lacks exceptions this is important as it allows you to avoid checking all the time for invalid values, whilst still being able to know if the end result of your computation was ever affected by an invalid numerical operation.
Correct, but I'd like to point out that NaNs are a bit more sophisticated than just "numeric contagion".
1) NaNs carry payload, so you can actually identify what sort of calculation failed. E.g. NaN-27 might mean "logarithm of a negative number", while NaN-95 might be "inverse trig function domain error". Any calculation involving a single NaN is supposed to propagate the same payload, so at the end of the calculation you can see that you tried to take the log of a negative number and debug accordingly.
2) On rare occasions, NaNs can validly disappear from a calculation, leaving you with a non-NaN answer. The rule is, if you can replace the NaN with *any* other value, and still get the same result, then the NaN is irrelevant and can be consumed. William Kahan gives an example:
For example, 0*NaN must be NaN because 0*∞ is an INVALID operation (NaN). On the other hand, for hypot(x, y) := √(x*x + y*y) we find that hypot(∞, y) = +∞ for all real y, finite or not, and deduce that hypot(∞, NaN) = +∞ too; naive implementations of hypot may do differently.