Java で数値が NaN かどうかをチェックする方法

JavaJavaBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Java で浮動小数点数が「非数」(NaN: Not a Number) であるかどうかをチェックする方法を学びます。Double.isNaN() メソッドを調べ、浮動小数点演算によって NaN 値がどのように生成されるかを理解し、NaN チェックの文脈で非浮動小数点数の入力をどのように扱うかを検討します。この実験の終わりまでに、Java プログラムで NaN 値を確実に検出し管理できるようになります。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/SystemandDataProcessingGroup(["System and Data Processing"]) java(("Java")) -.-> java/BasicSyntaxGroup(["Basic Syntax"]) java(("Java")) -.-> java/StringManipulationGroup(["String Manipulation"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) 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: Not a Number) であるかどうかをチェックする方法を学びます。

コンピュータの浮動小数点数は、時に NaN と呼ばれる特殊な値になることがあります。これは、計算結果が未定義であるか、標準的な数値として表現できない場合に起こります。たとえば、ゼロをゼロで割ったり、負の数の平方根を求めたりすると、NaN が結果として返されます。

プログラムで NaN 値を検出できることは重要です。なぜなら、NaN 値は通常の数値とは異なる振る舞いをするからです。たとえば、標準的な比較演算子 (==, <, >) を使用して NaN 値を他の任意の数値 (別の NaN でさえも) と比較すると、常に false になります。

Java では、NaN をチェックするための特定のメソッド Double.isNaN() が用意されています。このメソッドは double 型の値を入力として受け取り、その値が NaN であれば true を返し、そうでなければ false を返します。

Double.isNaN() の使い方を示すために、簡単な Java プログラムを作成しましょう。

  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));
        }
    }

    このコードでは、以下のことを行っています。

    • 2 つの 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 を通常の数値として正しく識別したことを確認しています。

Java で NaN 値をチェックするには、Double.isNaN() を使用するのが正しく信頼性の高い方法です。直接比較 (== Double.NaN) に依存することはお勧めできません。なぜなら、前述のように NaN == NaNfalse と評価されるからです。

浮動小数点演算によるテスト

このステップでは、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 です。
    • result2Math.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 をもたらす 3 つの演算を正しく識別し、無限大の値と通常の数値を NaN ではないと正しく識別していることを示しています。

これらの異なる浮動小数点演算でテストすることで、NaN がいつ発生するか、およびプログラムでこれらのケースを処理するために Double.isNaN() をどのように使用するかをより深く理解することができます。

非浮動小数点入力の処理

前のステップでは、浮動小数点演算がどのようにして NaN をもたらすかに焦点を当てました。しかし、時には「テキスト」のような有効な数値ではない入力を受け取ることがあります。このような入力を浮動小数点数に変換しようとすると、問題が発生することがあります。

Double.isNaN() は浮動小数点計算の結果をチェックするためのものですが、最初の入力が数値として解析できないケースを処理することも重要です。Java には文字列を数値に解析するメソッドが用意されており、入力が無効な場合、これらのメソッドは例外をスローすることがあります。

ユーザー入力を double 型に解析し、解析された値が 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 で浮動小数点数が「非数 (Not a Number, NaN)」であるかどうかをチェックする方法を学びました。NaN は未定義または表現できない計算から生じる特殊な値であり、標準の比較演算子は NaN との比較では信頼性が低いことを発見しました。

具体的には、Double.isNaN() メソッドの使用に焦点を当てました。これは Java で NaN 値を正確に検出するための標準的かつ推奨される方法です。NaN を生成する浮動小数点演算や通常の数値結果を伴う例を用いて、その使い方を実証しました。