如何在 Java 中检查数字是否为 NaN

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,你将学习如何在 Java 中检查一个浮点数是否为「非数字」(NaN)。我们将探讨 Double.isNaN() 方法,了解如何通过浮点运算生成 NaN 值,并思考在 NaN 检查的场景下如何处理非浮点输入。在本实验结束时,你将能够在 Java 程序中可靠地检测和处理 NaN 值。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java/BasicSyntaxGroup -.-> java/data_types("Data Types") java/BasicSyntaxGroup -.-> java/math("Math") java/StringManipulationGroup -.-> java/strings("Strings") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/user_input("User Input") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/exceptions("Exceptions") java/SystemandDataProcessingGroup -.-> java/math_methods("Math Methods") subgraph Lab Skills java/data_types -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} java/math -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} java/strings -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} java/user_input -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} java/exceptions -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} java/math_methods -.-> lab-559965{{"如何在 Java 中检查数字是否为 NaN"}} end

使用 Double.isNaN() 进行检查

在这一步中,你将学习如何在 Java 中使用 Double.isNaN() 方法来检查一个浮点数是否为「非数字」(NaN)。

计算机中的浮点数有时会产生一个名为 NaN 的特殊值。当计算结果未定义或无法表示为标准数字时,就会出现这种情况。例如,零除以零或对负数取平方根都会产生 NaN。

能够在程序中检测 NaN 值非常重要,因为它们的行为与常规数字不同。例如,使用标准比较运算符(==<>)将 NaN 值与任何其他数字(即使是另一个 NaN)进行比较,结果始终为 false

Java 提供了一个特定的方法来检查 NaN:Double.isNaN()。该方法接受一个 double 类型的值作为输入,如果该值是 NaN,则返回 true,否则返回 false

让我们创建一个简单的 Java 程序来演示如何使用 Double.isNaN()

  1. 在 WebIDE 编辑器中打开 HelloJava.java 文件。

  2. 将现有代码替换为以下内容:

    public class CheckNaN {
        public static void main(String[] args) {
            double result1 = 0.0 / 0.0; // This will result in NaN
            double result2 = 10.0 / 2.0; // This is a regular number
    
            System.out.println("Is result1 NaN? " + Double.isNaN(result1));
            System.out.println("Is result2 NaN? " + Double.isNaN(result2));
        }
    }

    在这段代码中:

    • 我们声明了两个 double 类型的变量 result1result2
    • result1 被赋值为 0.0 / 0.0 的结果,这是一个不定型,会产生 NaN。
    • result2 被赋值为 10.0 / 2.0 的结果,这是一个标准数字(5.0)。
    • 然后,我们使用 Double.isNaN() 来检查 result1result2 是否为 NaN,并打印结果。
  3. 保存文件(Ctrl+S 或 Cmd+S)。

  4. 现在,我们需要编译这个新程序。由于我们将类名更改为 CheckNaN,因此需要编译 CheckNaN.java。打开终端并运行:

    javac CheckNaN.java

    如果编译成功,你应该看不到任何输出。

  5. 最后,运行编译后的程序:

    java CheckNaN

    你应该会看到类似以下的输出:

    Is result1 NaN? true
    Is result2 NaN? false

    这个输出证实了 Double.isNaN() 正确地将 result1 识别为 NaN,将 result2 识别为常规数字。

使用 Double.isNaN() 是在 Java 中检查 NaN 值的正确且可靠的方法。不建议使用直接比较(== Double.NaN),因为如前所述,NaN == NaN 的计算结果为 false

进行浮点运算测试

在这一步中,我们将探索更多可能产生 NaN 的浮点运算示例,并练习使用 Double.isNaN() 方法来检查这些情况。了解哪些运算会产生 NaN 对于编写能够优雅处理潜在错误的健壮 Java 代码至关重要。

除了零除以零之外,其他涉及无穷大或无效数学函数的运算也可能产生 NaN。Java 对正无穷和负无穷有特殊的表示(Double.POSITIVE_INFINITYDouble.NEGATIVE_INFINITY)。

让我们修改 CheckNaN.java 程序来测试其中一些情况。

  1. 在 WebIDE 编辑器中打开 CheckNaN.java 文件。

  2. 将现有代码替换为以下内容:

    public class CheckNaN {
        public static void main(String[] args) {
            double result1 = 0.0 / 0.0; // NaN
            double result2 = Math.sqrt(-1.0); // NaN (square root of a negative number)
            double result3 = Double.POSITIVE_INFINITY - Double.POSITIVE_INFINITY; // NaN
            double result4 = 10.0 / 0.0; // Positive Infinity
            double result5 = -10.0 / 0.0; // Negative Infinity
            double result6 = 5.0; // Regular number
    
            System.out.println("Is result1 NaN? " + Double.isNaN(result1));
            System.out.println("Is result2 NaN? " + Double.isNaN(result2));
            System.out.println("Is result3 NaN? " + Double.isNaN(result3));
            System.out.println("Is result4 NaN? " + Double.isNaN(result4));
            System.out.println("Is result5 NaN? " + Double.isNaN(result5));
            System.out.println("Is result6 NaN? " + Double.isNaN(result6));
        }
    }

    在这个更新后的代码中:

    • result1 仍然是 0.0 / 0.0
    • result2 使用 Math.sqrt(-1.0),这在实数范围内是数学上未定义的,会产生 NaN。
    • result3 是正无穷减去正无穷,这是另一种不定型,结果为 NaN。
    • result4result5 展示了除以零的情况,结果分别为正无穷或负无穷,而不是 NaN。
    • result6 是一个用于对比的普通数字。
  3. 保存文件(Ctrl+S 或 Cmd+S)。

  4. 在终端中编译修改后的程序:

    javac CheckNaN.java

    同样,没有输出表示编译成功。

  5. 运行程序:

    java CheckNaN

    你应该会看到类似以下的输出:

    Is result1 NaN? true
    Is result2 NaN? true
    Is result3 NaN? true
    Is result4 NaN? false
    Is result5 NaN? false
    Is result6 NaN? false

    这个输出表明,Double.isNaN() 正确地识别出了三种产生 NaN 的运算,同时也正确地将无穷大值和普通数字识别为非 NaN。

通过对这些不同的浮点运算进行测试,你能更好地理解 NaN 何时会出现,以及如何在程序中使用 Double.isNaN() 来处理这些情况。

处理非浮点输入

在前面的步骤中,我们重点关注了浮点运算如何产生 NaN。然而,有时你可能会收到根本不是有效数字的输入,比如文本。当你尝试将这类输入转换为浮点数时,也会引发问题。

虽然 Double.isNaN() 专门用于检查浮点计算的结果,但处理初始输入无法解析为数字的情况同样重要。Java 提供了将字符串解析为数字的方法,如果输入无效,这些方法会抛出异常。

让我们创建一个新程序,尝试将用户输入解析为双精度浮点数,然后检查解析后的值是否为 NaN。

  1. ~/project 目录下创建一个名为 ParseAndCheck.java 的新文件。你可以在文件资源管理器中右键单击,选择「新建文件」,然后输入 ParseAndCheck.java

  2. 在 WebIDE 编辑器中打开 ParseAndCheck.java 文件,并添加以下代码:

    import java.util.Scanner;
    
    public class ParseAndCheck {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.print("Enter a floating-point number or an expression (e.g., 0.0/0.0): ");
            String input = scanner.nextLine();
    
            try {
                double value = Double.parseDouble(input);
    
                if (Double.isNaN(value)) {
                    System.out.println("The input resulted in NaN.");
                } else {
                    System.out.println("The input is a valid number: " + value);
                }
            } catch (NumberFormatException e) {
                System.out.println("Invalid input: Could not parse as a number.");
            } finally {
                scanner.close();
            }
        }
    }

    让我们来分析一下这段代码:

    • 我们导入 Scanner 类以读取用户输入。
    • 我们提示用户输入一个字符串。
    • 我们使用 try-catch 块来处理解析过程中可能出现的错误。
    • Double.parseDouble(input) 尝试将输入字符串转换为 double 类型。如果字符串不是有效的数字格式(例如 "hello"),它将抛出 NumberFormatException
    • try 块中,如果解析成功,我们使用 Double.isNaN(value) 检查得到的 double 值是否为 NaN。
    • catch 块捕获 NumberFormatException,并在输入无法解析时打印错误消息。
    • finally 块确保关闭扫描器。
  3. 保存文件(Ctrl+S 或 Cmd+S)。

  4. 在终端中编译程序:

    javac ParseAndCheck.java
  5. 运行程序:

    java ParseAndCheck

    程序会提示你输入。尝试输入不同的值:

    • 输入 5.5
      Enter a floating-point number or an expression (e.g., 0.0/0.0): 5.5
      The input is a valid number: 5.5
    • 输入 0.0/0.0
      Enter a floating-point number or an expression (e.g., 0.0/0.0): 0.0/0.0
      Invalid input: Could not parse as a number.
      (注意:parseDouble 不能直接计算数学表达式。它只能解析数字的字符串表示。)
    • 输入 NaN
      Enter a floating-point number or an expression (e.g., 0.0/0.0): NaN
      The input resulted in NaN.
    • 输入 hello
      Enter a floating-point number or an expression (e.g., 0.0/0.0): hello
      Invalid input: Could not parse as a number.

这一步展示了如何将输入解析与 Double.isNaN() 检查相结合,以处理各种类型的输入,包括有效数字、字符串 "NaN" 和无效的数字格式。这是处理来自外部源的浮点数时,应对潜在问题的更全面的方法。

总结

在本次实验中,我们学习了如何在 Java 中检查一个浮点数是否为「非数字」(NaN)。我们了解到,NaN 是一种特殊的值,它是由未定义或无法表示的计算产生的,并且标准比较运算符在处理 NaN 时不可靠。

我们特别关注了 Double.isNaN() 方法的使用,这是在 Java 中准确检测 NaN 值的标准且推荐的方法。我们通过涉及产生 NaN 的浮点运算和常规数值结果的示例,演示了该方法的用法。