今天在學習集合框架的時候,看源碼發現了一個不是很理解的問題(Float源碼):
/**
* 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.
*/
public static boolean isNaN(float v) {
return (v != v);
}
判斷isNan爲什麼是v != v ,what???這不是判斷兩個float是否相等麼?
我們仔細看一下上面的註釋:
如果指定的參數(float v入參)是NAN,返回true,否則就是false
NAN :Not-a-Number(不是一個數字)
從上面我們可以分析出來:意思就是兩個NaN用==比較的結果會得到false。
校驗一下:
float firstNan=Float.NaN;
float secoenNan=Float.NaN;
System.out.println("firstNan!=secoenNan = "+(firstNan!=secoenNan));
打印的結果:
firstNan!=secoenNan = true
到底什麼是NAN?我們查閱一下資料,維基百科上得到如下的結果:
有點晦澀,下面我們具體講解一下
1、什麼是NAN?
簡單地說,NaN是一個數字數據類型值,代表“不是數字”。NAN通常表示無效操作的結果,Java將float和double類型的NaN常量定義爲Float .NaN和Double.NaN:
“ 持有類型爲double的非數字(NaN)值的常量。它相當於Double.longBitsToDouble(0x7ff8000000000000L)返回的值。”
“保持float類型的非數字(NaN)值的常量。它等同於Float.intBitsToFloat(0x7fc00000)返回的值。”
我們猜一下下面的結果:
運行代碼:
System.out.println("0 / 0 = " + (0 / 0));
是的,你猜對了ArithmeticException
輸出結果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.test.BaseTest.main(BaseTest.java:25)
現在猜猜輸:
運行代碼
System.out.println("0.0 / 0.0 = " + (0.0 / 0.0));
猜對了嗎?
0.0 / 0.0 = NaN
double和float所有的,對於Java中的其他數值數據類型,我們沒有這種類型的常量。
2、NAN的校驗與比較
在java中編寫代碼時,我們應該注意檢查輸入是否有效且在預期範圍內。在大多數情況下,NaN值不是有效輸入。因此,我們應該驗證輸入值不是NaN值並適當地處理這些輸入值。
NaN無法與任何浮動類型值進行比較。這意味着我們會得到虛假的涉及所有的比較操作的NaN(除“!=”爲此我們得到真正的)。
測試代碼如下
float Nan = Float.NaN;
System.out.println("(NaN == 1) = "+(Nan == 1));
System.out.println("(Nan > 1) = "+(Nan > 1));
System.out.println("(Nan < 1) = " + (Nan < 1));
System.out.println("(NaN != 1) = " + (Nan != 1));
System.out.println("(NaN == NaN) = " + (Nan == Nan));
System.out.println("(NaN > NaN) = " + (Nan > Nan));
System.out.println("(NaN < NaN) = " + (Nan < Nan));
System.out.println("(NaN != NaN) = " + (Nan != Nan));
得到結果如下;
(NaN == 1) = false
(Nan > 1) = false
(Nan < 1) = false
(NaN != 1) = true
(NaN == NaN) = false
(NaN > NaN) = false
(NaN < NaN) = false
(NaN != NaN) = true
在我們的代碼中校驗是否爲NAN值,我們可以使用:Float.isNaN和Double.isNaN方法來檢查這些值,這種方法易讀易懂。、
3、isNan()和isInfinite()的區別
NaN:非數值類型;
Infinite:無窮大(包含正無窮大、負無窮大);
總結:
在Java的計算中,在執行涉及float和double類型的操作時,可能會產生NaN值。一些浮點方法和操作產生NaN值而不是拋出異常。我們可能需要明確處理這些結果,我們可以使用:Float.isNaN和Double.isNaN方法來檢查;