質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

Javaにおける逆ポーランド記法について

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 607

ryotazumi

score 8

前提・実現したいこと

Javaにおいて、逆ポーランド記法のコードを書いています。

発生している問題・エラーメッセージ

Exception in thread "main" java.lang.NumberFormatException: empty String
    at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
    at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
    at java.base/java.lang.Double.parseDouble(Double.java:543)
    at rensyu1/rensyu4.Calculator.getAnswer(Calculator.java:52)
    at rensyu1/rensyu4.CalculatorMain.main(CalculatorMain.java:12)

該当のソースコード

public class Stack {
    private static final int DEFAULT_INIT_SIZE = 16;

    private int capacity;
    private int size;
    private String[] dataSet;

    public Stack() {
        this(DEFAULT_INIT_SIZE);
    }

    public Stack(int initSize) {
        capacity = initSize;
        size = 0;
        dataSet = new String[capacity];
    }

    public boolean isEmpty() {
        if (size == 0) {
            return true;
        }
        else {
            return false;
        }
    }

    public void push(String s) {
        if (size < capacity) {
            for (int i = capacity - 1; i > 0; i--)
                dataSet[i] = dataSet[i - 1];
            dataSet[0] = s;
            size = size + 1;
        }
        else if (size == capacity) {
            doubleCapacity();
            for (int i = capacity - 1; i > 0; i--)
                dataSet[i] = dataSet[i - 1];
            dataSet[0] = s;
            size = size + 1;
        }
    }

    public String pop() {
        if (size == 0) {
            return "";
        }
        else {
            String top = dataSet[0];
            for (int i = 0; i < capacity -1; i++)
                dataSet[i] = dataSet[i + 1];
            dataSet[capacity - 1] = null;
            size = size - 1;
            return top;
        }
    }

    public String peek() {
        if (size == 0) {
            return "";
        }
        else {
            return dataSet[0];
        }
    }

    private void doubleCapacity() {
        System.out.println("Capacity: "+capacity+"->"+2*capacity);
        String[] datakeep = new String[capacity];
        for (int i = 0; i < capacity; i++)
            datakeep[i] = dataSet[i];
        capacity = 2 * capacity;
        dataSet = new String[capacity];
        for (int i = 0; i < capacity / 2; i++)
            dataSet[i] = datakeep[i];
    }
}

class Calculator {
    private boolean isOperator (String token) {
        if (token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/")) {
            return true;
        }
        else {
            return false;
        }
    }

    private boolean isNumber (String token) {
        if (token == "0" || token == "1" || token == "2" || token == "3" || token == "4" || token == "5" || token == "6" || token == "7" || token == "8" || token == "9") {
            return true;
        }
        else {
            return false;
        }
    }
    public double getAnswer (String equation) {
        int count = equation.length();
        int initSize = 4;
        Stack stack = new Stack(initSize);
        String a;
        String b;
        double x = 0;
        double y = 0;
        for (int i = 0; i < count; i++) {
            String s = equation.substring(i, i + 1);
            if (isOperator(s)) {
                a = stack.pop();
                b = stack.pop();
                x = Double.parseDouble(a);
                y = Double.parseDouble(b);
                switch (s) {
                    case "+": x = x + y; break;
                    case "-": x = y - x; break;
                    case "*": x = x * y; break;
                    case "/": x = y / x; break;
                }
                a = String.valueOf(x);
                stack.push(a);
            }
            else if (isNumber(s)) {
                stack.push(s);
            }
        }
        a = stack.pop();
        x = Double.parseDouble(a);
        return x;
    }
}

import java.util.Scanner;

public class CalculatorMain {
    public static void main(String[] args) {
        Scanner stdIn = new Scanner(System.in);
        System.out.println("算術式を逆ポーランド記法で入力してください。");
        String equation = stdIn.next();
        stdIn.close();
        Calculator calculator =new Calculator();
        double answer = calculator.getAnswer(equation);
        System.out.println("Answer = "+ answer);
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

 エラーの原因 

  • オペランドもオペレータも正しく判定されないのでStackが空のまま
    文字列は==でなくequals()で判定してください。
  • 常に割り算の結果がスタックにプッシュされる
    オペレータの処理で case +-*/にそれぞれbreak;を追加してください。

Stackの改善点

  • オペランドスタックの型
    Stringではなくdoubleでよいでしょう。
  • 配列
    追加  /削除の都度、要素を移動する必要はありません。配列の末尾がスタックのトップだとすれば移動は不要。
    拡張にはSystem.arraycopyを使うと良いでしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/25 02:20

    直したところ上手くいきました!助かりました。ありがとうございます!

    キャンセル

0

エラーの原因を知りたいのですか?エラーメッセージに書いてある通りです。
Exception in thread "main" java.lang.NumberFormatException: empty String
NumberFormatException という例外が出ています。内容は empty String つまり空の文字列は数値ではないよということ。
後続のスタックトレースで注目するのは、自身で書いたコードとシステム側のコードの境目。今回はここ。
    at java.base/java.lang.Double.parseDouble(Double.java:543)     at rensyu1/rensyu4.Calculator.getAnswer(Calculator.java:52)
Calculator.javaの52行目にあるparseDoubleというメソッドに渡されている文字列が数値じゃなく空であると予想できます。デバッグでステップ実行すれば中身がわかります。このようにエラーの原因を探っていってみてください。

なんとなくequationが空であると予想がつきますが。

(文章の最後が切れていたので編集しました。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/24 22:36

    速やかな回答ありがとうございます。
    エラーの概要がなんとなくわかりました。

    Calculatorクラスの、String s = equation.substring(i, i + 1);が問題な気がします。
    どう改善できるかお力添えいただきたいです。よろしくお願いいたします。

    キャンセル

  • 2020/05/24 22:40

    不具合のあたりはついているのだから、あとは自力でがんばってください。
    いろいろな入力を試してみて、デバッグで経過を追いかけていけばわかるでしょう。

    キャンセル

  • 2020/05/24 23:13

    ありがとうございます!

    キャンセル

0

直接の原因ではないかもですが…

Javaの文字列比較は==でななくequalsです。

token == "+"

token.equals("+")

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/24 23:21

    ご指摘ありがとうございます。直してみました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る