W Javie „NaN” oznacza „Not a Number”. Nie jest to typ wyjątku, raczej zaskakująco, typ danych NaN jest również liczbą. Ale często, gdy początkujący programiści dostają go nieumyślnie, używają go dalej w swoich obliczeniach. W związku z tym niekompatybilne typy danych w Javie, gdy są używane razem, mogą powodować zgłaszany błąd. Powszechnie uważa się również, że
java.lang.ArithmeticException: / by zero
jest uważany za taki sam jak NaN. Jednak Java traktuje je oba inaczej. Wystarczająco zastanawiające? Aby uzyskać kompleksowe zrozumienie, przeanalizujemy, w jaki sposób różnią się one od siebie. Pod koniec tego artykułu dowiesz się o możliwych operacjach generujących nie liczbę (nan) i kilku prostych sposobach radzenia sobie z tym.
Co to jest NaN?
Czym więc jest NaN? „NaN”, jak wielu z was się domyśliło, jest używane do reprezentowania „Not a Number” w Javie. Jest to specjalna wartość zmiennoprzecinkowa do oznaczania przepełnień i błędów. Jest generowany, gdy liczba zmiennoprzecinkowa jest dzielona przez zero lub gdy obliczany jest pierwiastek kwadratowy z liczby ujemnej. Na przykład spójrz na poniższy fragment.
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
}
}
Wyjście
NaN
NaN
NaN
W powyższym fragmencie można zaobserwować, że NaN powstaje w wyniku 3 prostych operacji:
- Dzielenie
float / double
zera przez zero. - Biorąc pod pierwiastek z liczby ujemnej (Math.sqrt(-x)). W matematyce pierwiastek kwadratowy z liczby ujemnej daje liczbę urojoną . Ten przypadek jest rozwiązywany przez zwrócenie NaN w Javie.
- Biorąc mod liczby z zerem, zwróci resztę po podzieleniu wartości przez zero. Dlatego NaN jest zwracane.
Czym NaN różni się od dodatniej i ujemnej nieskończoności?
Zgodnie ze specyfikacją IEEE 754 istnieją trzy specjalne wartości zmiennoprzecinkowe i podwójne do obsługi przypadków granicznych:- Pozytywna nieskończoność
- Ujemna nieskończoność
- NaN
Czym jest metoda NaN()?
isNaN()
jest jedną z podstawowych metod w Javie, aby sprawdzić, czy jest to wartość NaN, czy nie. Jak omówiliśmy powyżej trzy przypadki, nadszedł czas, aby przetestować, w jaki sposób metoda isNaN() rozróżnia wartości +infinity , -infinity i 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());
}
}
Wyjście
+Infinity.IsNaN() = false
-Infinity.IsNaN() = false
NaN.IsNaN() = true
Jak porównać wartości NaN?
Każda wartość NaN jest uważana za odrębną. Oznacza to, że żaden pojedynczy NaN nie jest równy żadnemu innemu NaN. Zgodnie z tą zasadą, jeśli porównasz jedną wartość z drugą, wynik jest zawsze ujemny. Ponieważ NaN jest nieuporządkowany, więc porównanie numeryczne obejmujące nawet pojedynczy NaN zwraca wartość false. Java udostępnia Float.NaN i Double.NaN dla pól stałych w obu klasach w celu przeprowadzenia porównań. Możemy je rozróżnić w dwóch oddzielnych scenariuszach:- Prawda: Tylko w przypadku równości (!=)
- Fałsz: dla wszystkich operandów porównania (==, <=, >=, <, >)
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
}
}
Jak wygenerować wartości NaN?
Zanim zakończymy, spójrzmy na kilka typowych przykładów uzyskania Not a Number (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));
}
}
Wyjście:
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
GO TO FULL VERSION