There are three kinds of operation which return NaN:[4]
- Operations with a NaN as at least one operand
- Indeterminate forms
- The divisions 0/0, ∞/∞, ∞/−∞, −∞/∞, and −∞/−∞
- The multiplications 0×∞ and 0×−∞
- The additions ∞ + (−∞), (−∞) + ∞ and equivalent subtractions
- The standard has alternative functions for powers:
- The standard pow function and the integer exponent pown function define 00, 1∞, and ∞0 as 1.
- The powr function define all three indeterminate forms as invalid operations and so returns NaN.
- Real operations with complex results, for example:
- The square root of a negative number
- The logarithm of a negative number
- The inverse sine or cosine of a number which is less than −1 or greater than +1.
NaNs may also be explicitly assigned to variables, typically as a representation for missing values. Prior to the IEEE standard, programmers often used a special value (such as −99999999) to represent undefined or missing values, but there was no guarantee that they would be handled consistently or correctly.[1]
NaNs are not necessarily generated by the processor. In the case of quiet NaNs, the first item is always valid for each processor; the others may not necessarily be. For example, on the Intel Architecture processors, the FPU never creates a NaN except in the first case, unless the corresponding floating point exception mask bits have been set.[5] The other items would cause exceptions, not NaNs. However, the software exception handler may examine the operands and decide to return a NaN (e.g. in the case of 0/0).
[edit]Quiet NaN
Quiet NaNs, or qNaNs, do not raise any additional exceptions as they propagate through most operations. The exceptions are where the NaN cannot simply be passed through unchanged to the output, such as in format conversions or certain comparison operations (which do not "expect" a NaN input).
[edit]Signaling NaN
Signaling NaNs, or sNaNs, are special forms of a NaN which when consumed by most operations should raise an invalid exception and then, if appropriate, be "quieted" into a qNaN which may then propagate. They were introduced in IEEE 754. There have been several ideas for how these might be used:
- Filling uninitialized memory with signaling NaNs would produce an invalid exception if the data is used before it is initialized
- Using an sNaN as a placeholder for a more complicated object, such as:
When encountered a trap handler could decode the sNaN and return an index to the computed result. In practice this approach is faced with many complications. The treatment of the sign bit of NaNs for some simple operations (such as absolute value) is different from that for arithmetic operations. Traps are not required by the standard. There are other approaches to this sort of problem which would be more portable.
NaN是Not a Number的缩写,就是说它不是一个数。NaN是定义在IEEE 754标准中的特殊值,类似的特殊值还有INF(无穷大,INFinite)。IEEE 754是定义浮点数的标准,有1985和2008两个版本。其中,2008版本还定义了十进制浮点数的标准。
NaN的产生(可以)是这样的(此段文字摘译自WIKI):
1)NaN参与数学运算的结果仍是NaN
2)0/0,正无穷大/正无穷大,正无穷大/负无穷大,负无穷大/正无穷大,负无穷大/负无穷大
3)0和正/负无穷大相乘
4)正无穷大+负无穷大,负无穷大加正无穷大
5)数学上无解的一些函数值,比如:负数的平方根,对2.0的求反正弦,等等
第一条说明了NaN在运算中的“传染性”。如果不慎在某处引入了NaN,那么之后的算式值很可能就一直是NaN了。所以在涉及浮点数值运算时一定要注意NaN的存在。
回过头来解释前面的题目:NaN永远不等于自己,所以说NaN == NaN永远为false,而NaN != NaN永远为true。这是一个相当特殊的情况:即使参与比较的两个NaN的内存表示是一模一样的,但它们仍然是不等的。
更深一步地说,NaN有两种,一种是Quiet NaN,另一种是Signalling NaN。在使用时,Signalling NaN会立即引发异常,然后将自身变为Quiet NaN;Quiet NaN的行为比较安静,在算术运算中它不会引发异常,只是将运算结果“传染”为NaN(但是在某些不接受NaN的地方仍会引发异常)。
INF,它溢出到无穷大
INF就是无穷大,在浮点数中,有+INF和-INF两种。INF在数学上有对应的概念,所以它比NaN更好理解一些。比如用1/0,得到的结果就是INF
0,它竟然还有正负
在IEEE浮点数中,0也是特殊的,因为它有+0和-0两种(“正零”和“负零”)。其中,1除以“负0”等于“负无穷大”,1除以“正0”等于“正无穷大”。
舍入,它可不是“四舍五入”
舍入算法对我们多数人来说意味着“四舍五入”。这个在上学时就学过了,但它却会给舍入之后的数带来扩大的趋势。在买卖方之间,民俗传统中一直有“五 刨六撩”一说,“五刨”是说将5及5以下的舍去,“六撩”是说将6及6以上的进位,这种舍入算法有整体减小的趋势,体现了小生意人让利的“诚意”。那么, 更好的舍入算法是什么样的呢?
IEEE754中定义了最基本的舍入算法:Rounds to nearest, ties to even(even在这里是“偶数”的意思)。这种算法将4及4以下的数抛弃,6及6以上的数进位,如果要舍入的最高位是5的话,则将要保留的最低位圆整 到最接近的偶数(这里说的“偶数”包括0)。比如:
89.64 --> 90
98.46 --> 98
1919.54 --> 1920
1918.55 --> 1918
对于大量均匀分布的数来说,这种50%概率算法保证了舍入后的数没有放大或者缩小的趋势。在银行里都是用的这种算法,做过金融类程序的对此应该印象深刻的。
除了上面提到的“Ties To Even算法”之外,还有几种舍入算法,因为定义得非常清晰和明确,这里不再多说,详情请见参考资料。
参考资料/延伸阅读
1、http://en.wikipedia.org/wiki/IEEE_754-2008
2、http://en.wikipedia.org/wiki/IEEE_754-1985
3、http://en.wikipedia.org/wiki/Signed_zero
4、http://en.wikipedia.org/wiki/Not_a_Number
5、IEEE标准
以上这篇文章zz自 http://blog.csdn.net/yuankaining/archive/2009/08/19/4461238.aspx
这个问题是在看Fundamentals of Computer Graphics的时候看到的!总结一下:
当深入理解了IEEE标准和NAN之后,我们完全可以改善程序的设计来避免复杂的判断!这一点是完全可以做到的!注意Signalling NaN 和Quiet NaN