在学习Java集合的时候遇到了Float.isNaN(float)函数,点进去一看就不理解了,函数实现以下:html
public static boolean isNaN(float v) { return (v != v); }
float的v怎么会不等于自身呢?如下是关于这个函数的描述:java
/** * Returns {@code true} if the specified number is a * Not-a-Number (NaN) value, {@code false} otherwise. * * @param v the value to be tested. * @return {@code true} if the argument is NaN; * {@code false} otherwise. */
isNaN():
描述:返回一个 Boolean 值,指明提供的值是不是保留值 NaN (不是数字)。
语法:isNaN(numvalue)numvalue 参数是要检查是否为 NaN 的值。
说明:若是值是 NaN, 那么 isNaN 函数返回 true ,不然返回 false 。
从上述描述能够知道,这个函数判断一个float参数是否是NaN(Not a Number),即不是一个数字,那么什么是NaN,什么状况下会出现NaN呢?ide
定义: 函数
NaN(Not a Number,非数)是计算机科学中数值数据类型的一个值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。学习
会返回NaN的运算:测试
Java中的NaN:ui
Java虚拟机在处理浮点数运算时,不会抛出任何运行时异常(这里所讲的是java语言中的异常,请勿与IEEE 754规范中的浮点异常相互混淆,IEEE 754的浮点异常是一种运算信号),当一个操做产生溢出时,将会使用有符号的无穷大来表示,若是某个操做结果没有明确的数学定义的话,将会使用NaN值来表示,全部使用NaN值做为操做数的算术操做,结果都返回NaN。Java中的Double和Float中都有isNaN函数,判断一个数是否是NaN,其实现都是经过上述 v != v 的方式,由于NaN是惟一与本身不相等的值,NaN与任何值都不相等。有些操做会使isNaN返回True,例如:this
System.out.println(Float.isNaN(0.0f / 0.0f)); System.out.println(Double.isNaN(Math.sqrt(-1)));
Double的NaN定义:spa
/** * A constant holding a Not-a-Number (NaN) value of type * {@code double}. It is equivalent to the value returned by * {@code Double.longBitsToDouble(0x7ff8000000000000L)}. */ public static final double NaN = 0.0d / 0.0;
以上定义了一个常量型的NaN,它的效果和Double.longBitsToDouble(0x7ff8000000000000L)的返回值是同样的,咱们能够看看Double.longBitsToDouble中的定义:code
If the argument is any value in the range 0x7ff0000000000001L through 0x7fffffffffffffffL or in the range 0xfff0000000000001L through 0xffffffffffffffffL, the result is a NaN. No IEEE 754 floating-point operation provided by Java can distinguish between two NaN values of the same type with different bit patterns.
如上可知,二进制的0x7ff0000000000001L~0x7fffffffffffffffL 和 0xfff0000000000001L~0xffffffffffffffffL 之间的数值是被定义成NaN类型,相似正无穷大和负无穷大,但又有区别。在Float中也相似。
总之,在实际数值计算的过程当中可能会出现一些非法的操做,致使产生了非法的数值,好比说除零,经过NaN来表示这样一个非数值,NaN与任何浮点数(包括自身)的比较结果都为假,即 (NaN ≠ x) = false,这是NaN独有的特性,因此可使用与本身相比来肯定当前数值是否是一个正常的数。
简单测试:
@Test public void NanTest() { Float f1 = new Float(-1.0 / 0.0); Float f2 = new Float(0.0 / 0.0); Double f3 = Math.sqrt(-1); // returns true if this Float value is a Not-a-Number(NaN), else false System.out.println(f1 + " = " + f1.isNaN()); System.out.println(f2 + " = " + f2.isNaN()); System.out.println(f3 + " = " + f3.isNaN()); System.out.println(Double.isNaN(Double.longBitsToDouble(0x7ff0000000000011L))); }
再看看这边的解释:Double.NaN != Double.NaN
还有一点须要注意:在将一个float的NaN窄化转换为整数类型T(T限于int或long类型之一)的时候,那转换结果就是int或long类型的0;而double类型的NaN值将按规定转换为float类型的NaN值。
参考资料: