CodeGym /Java 博客 /随机的 /Java 中的 NaN
John Squirrels
第 41 级
San Francisco

Java 中的 NaN

已在 随机的 群组中发布
在 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 的小习惯,可以避免很多麻烦。即使您一开始忘记了这一点,也没关系。您可以随时查阅本文以进行小的故障排除。经过多年的经验,一次性创建可编译、无错误的代码。因此,让我们亲自动手编写代码,并构建一些很棒的东西!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION