在 Java 中,“NaN”代表“不是數字”。這不是一種異常類型,令人驚訝的是,NaN 的數據類型也是一個數字。但往往當新手程序員無意中得到它時,他們會在計算中進一步使用它。因此,Java 中不兼容的數據類型一起使用時會導致可拋出的錯誤。通常也可以看到它java.lang.ArithmeticException: / by zero被認為與 NaN 相同。然而,Java 以不同的方式對待它們。夠令人費解嗎?為了您的全面理解,我們將剖析它們之間的區別。到本文結束時,您將了解可能產生非數字 (nan) 的操作,以及一些處理它的簡單方法。

什麼是南?

那麼,NaN 是什麼?許多人已經猜到“NaN”在 Java 中用來表示“非數字”。它是一個特殊的浮點值,用於表示溢出和錯誤。當浮點數除以零或計算負數的平方根時生成。Java 中的 NaN - 1例如,看看下面的片段。

public class NaN
{
    public static void main(String[]args)
    {
        System.out.println(0.0 / 0.0);	  //zero divided by zero
        System.out.println(Math.sqrt(-1)); //take sqrt of negative number
        System.out.println(10.0 % 0);      //taking mod by zero	
    }
}
輸出

NaN                                                                                                                                           
NaN                                                                                                                                           
NaN
在上面的代碼片段中,您可以觀察到 NaN 是 3 個簡單操作的結果:
  • 零除以float / double零。
  • 取負數的根 (Math.sqrt(-x))。在數學中,對負數求平方根會得到一個虛數。這種情況通過在 Java 中返回 NaN 來處理。
  • 用零取模,將返回一個值除以零後的餘數。因此,返回 NaN。

NaN 與正無窮大和負無窮大有何不同?

根據 IEEE 754 規範,有三種特殊的浮點和雙精度值來處理邊界情況:
  • 正無窮大
  • 負無窮大
  • 鈉鹽
正數除以 0 的結果是正無窮大。類似地,負無窮大是負數除以零的結果。請注意,所有浮點值也適用於雙精度數據類型。浮點數有限的精度有時是不夠的。但是,我們將在後面的部分中看到 NaN 如何同時適用於 float 和 double。

什麼是 NaN() 方法?

isNaN()是 Java 中檢查它是否為 NaN 值的基本方法之一。正如我們上面討論的三種情況,是時候測試 isNaN() 方法如何區分+infinity-infinity和 NaN 值了。

public class isNaN
{ public static void main(String[]args)
  { 
    Double posInfinity = +2.0 / 0.0;
    Double negInfinity = -3.5 / 0.0;
    Double nanVal = 50 % 0.0;


    System.out.println ("+" + posInfinity + ".IsNaN() = " + posInfinity.isNaN());
    System.out.println ( negInfinity + ".IsNaN() = " + negInfinity.isNaN());
    System.out.println ( nanVal +  ".IsNaN() = " + nanVal.isNaN());
  }
}
輸出

+Infinity.IsNaN() = false                                                                                                                       
-Infinity.IsNaN() = false                                                                                                                       
NaN.IsNaN() = true

如何比較 NaN 值?

每個 NaN 值都被認為是不同的。這意味著,沒有一個 NaN 等於任何其他 NaN。根據這一原則,如果將一個值與另一個值進行比較,結果總是負數。由於 NaN 是無序的,因此即使涉及單個 NaN 的數字比較也會返回 false。Java 為這兩個類中的常量字段都提供了 Float.NaN 和 Double.NaN 來進行比較。我們可以在兩個不同的場景中區分它們:
  • True:僅在不相等的情況下 (!=)
  • False:對於所有比較操作數(==、<=、>=、<、>)
這是給你們的一個工作示例:

public class ComparingNaN
{ public static void main(String[] args)                                                                                                     
  {
    // Comparing NaN values for Float constants
    System.out.println (Float.NaN != Float.NaN); // true
    System.out.println (Float.NaN == Float.NaN); // false
    System.out.println (Float.NaN < Float.NaN);  // false
    System.out.println (Float.NaN > Float.NaN);  // false
    System.out.println (Float.NaN <= Float.NaN); // false
    System.out.println (Float.NaN >= Float.NaN); // false

    // Comparing NaN values for Float constants
    System.out.println (Double.NaN != Double.NaN); // true
    System.out.println (Double.NaN == Double.NaN); // false
    System.out.println (Double.NaN < Double.NaN);  // false
    System.out.println (Double.NaN > Double.NaN);  // false
    System.out.println (Double.NaN <= Double.NaN); // false
    System.out.println (Double.NaN >= Double.NaN); // false
  }
}

如何生成 NaN 值?

在結束之前,讓我們看一下獲取非數字 (nan) 的一些常見示例。

public class GenerateNaNValues {  
  static final float ZERO = 0;
  public static void main (String[]args)
  {
    System.out.println("ZERO / ZERO = " + (ZERO / ZERO));
    System.out.println("+INFINITY - INFINITY = " + 
    (Float.POSITIVE_INFINITY + Float.NEGATIVE_INFINITY));
    System.out.println("-INFINITY * ZERO = " + (Float.NEGATIVE_INFINITY * ZERO));
    System.out.println("+INFINITY * ZERO = " + (Float.POSITIVE_INFINITY * ZERO));
    System.out.println("log10(-10) = " +  Math.log(-10));
    System.out.println("√-10 = " + Math.sqrt(-10));
    System.out.println("NaN + 10 = " + (Float.NaN + 10));
    System.out.println("NaN - 10 = " + (Float.NaN - 10));
    System.out.println("NaN * 10 = " + (Float.NaN * 10));
    System.out.println("NaN / 10 = " + (Float.NaN / 10));
    System.out.println("NaN + NaN = " + (Float.NaN + Float.NaN));
    System.out.println("NaN - NaN = " + (Float.NaN - Float.NaN));
    System.out.println("NaN * NaN = " + (Float.NaN * Float.NaN));
    System.out.println("NaN / NaN = " + (Float.NaN / Float.NaN));
  }
}
輸出:

ZERO / ZERO = NaN                                                                                                                               
+INFINITY - INFINITY = NaN                                                                                                                      
-INFINITY * ZERO = NaN                                                                                                                          
+INFINITY * ZERO = NaN                                                                                                                          
log10(-10) = NaN                                                                                                                                
√-10 = NaN                                                                                                                                      
NaN + 10 = NaN                                                                                                                                    
NaN - 10 = NaN                                                                                                                                  
NaN * 10 = NaN                                                                                                                                  
NaN / 10 = NaN                                                                                                                                  
NaN + NaN = NaN                                                                                                                                 
NaN - NaN = NaN                                                                                                                                 
NaN * NaN = NaN                                                                                                                                 
NaN / NaN = NaN

結論

看過無數產生 NaN 的運算後,你現在一定很熟悉了。一開始您可能會感到困惑,但處理起來並不復雜。通過養成在雙精度/浮點計算中檢查值是否不是 NaN 的小習慣,可以避免很多麻煩。即使您一開始忘記了這一點,也沒關係。您可以隨時查閱本文以進行小的故障排除。經過多年的經驗,一次性創建可編譯、無錯誤的代碼。因此,讓我們親自動手編寫代碼,並構建一些很棒的東西!