首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用于正整数长计算的Java计算器

用于正整数长计算的Java计算器
EN

Code Review用户
提问于 2015-01-14 22:25:31
回答 1查看 1.6K关注 0票数 4

我正在制作一个计算器,它可以解决以非常原始的形式输入的计算。说:"3*52+11+3/2“我正在使用控制台,至少现在是这样。

这也将考虑到乘法和除法应该首先完成,所以2+3*4是14而不是20。

我希望有人看看是否有更有效的方法来做我正在做的事情,如果我没有做任何大的缺陷,或者在代码中有任何问题。此代码还假定用户输入有效文本,我将后者使其正确检查所有内容。

我试着尽可能地把所有事情都记录下来,这样就不需要太多的时间去理解逻辑了。

注意:我知道我的代码在输入负数时会崩溃,就像在-2+3中一样,而且现在还不支持十进制数。在执行这些建议方面提供任何帮助都是有益的。

代码语言:javascript
运行
复制
package com.fowlron.calculator;

import java.util.ArrayList;
import java.util.Scanner;

public class Calculator {
    private static ArrayList<Term> list = new ArrayList<Term>();

    public static void main(String args[]) {
        // Initial Info
        System.out.println("+ for sum");
        System.out.println("- for subtraction");
        System.out.println("* for multiplication");
        System.out.println("/ for division");
        System.out.println("E.g. 2+5*3 outputs 17");
        System.out.println("Input a calculation");

        // Opening scanner, getting input and closing it
        Scanner scan = new Scanner(System.in);
        String s = scan.nextLine();
        scan.close();

        // Looping through all chars in the input
        for (char c : s.toCharArray()) {
            if (isCharNumber(c)) {
                // Checking if the last character added was also a number
                // Also checking if size > 0 to avoid ArrayIndexOutOfBounds
                if (list.size() > 0
                        && list.get(list.size() - 1).getType()
                                .equals(Term.Type.DOUBLE)) {
                    // If so multiply by ten and add the new one
                    list.get(list.size() - 1).setNum(
                            list.get(list.size() - 1).getNum() * 10
                                    + Character.getNumericValue(c));
                } else {
                    // Otherwise, just add it regularly
                    list.add(new Term(Character.getNumericValue(c)));
                }
            } else {
                // If it's not a number, it must be an operator, so just add it
                // as a String
                // Also check for whitespaces
                if (!Character.isWhitespace(c)) {
                    list.add(new Term(Character.toString(c)));
                }
            }
        }

        // Calculating and outputting
        double result = calculate(list);
        System.out.println("The result is " + result);
    }

    private static boolean isCharNumber(char c) {
        // Thought that since it is very long I might want to put this into it's
        // own method
        if (c == '0' || c == '1' || c == '2' || c == '3' || c == '4'
                || c == '5' || c == '6' || c == '7' || c == '8' || c == '9') {
            return true;
        } else {
            return false;
        }
    }

    private static double calculate(ArrayList<Term> l) {
        // Creating a counter and a continue boolean
        int c = 0;
        boolean cont = true;

        // This loop is used twice because multiplications and divisions
        // have priority over sums and subtractions, so I need to first
        // solve all the multiplications and divisions, and only then the
        // others.
        // For example, 2+3*4 = 2+12 = 14
        // NOT 2+3*4 = 5*4 = 20

        while (cont) {
            // Checking if looped through all the elements
            if (c >= l.size()) {
                break;
            }

            // Checking if the current element is an operation
            if (l.get(c).getType().equals(Term.Type.STRING)) {
                // If so, check which it is, apply it to the previous element
                // and remove the next one followed by the current one
                Term p = l.get(c - 1);
                Term n = l.get(c + 1);
                switch (l.get(c).getOp()) {
                case "*":
                    p.setNum(p.getNum() * n.getNum());
                    l.remove(c + 1);
                    l.remove(c);
                    c--;
                    break;
                case "/":
                    p.setNum(p.getNum() / n.getNum());
                    l.remove(c + 1);
                    l.remove(c);
                    c--;
                    break;
                }
            }
            // Increasing the counter
            c++;
        }

        // Reseting the counter
        c = 0;
        while (true) {
            // Same logic here
            if (c >= l.size()) {
                break;
            }

            // Exactly the same only just for the sums and subtractions
            if (l.get(c).getType().equals(Term.Type.STRING)) {
                Term p = l.get(c - 1);
                Term n = l.get(c + 1);
                switch (l.get(c).getOp()) {
                case "+":
                    l.get(c - 1).setNum(p.getNum() + n.getNum());
                    break;
                case "-":
                    l.get(c - 1).setNum(p.getNum() - n.getNum());
                    break;
                }
                l.remove(c + 1);
                l.remove(c);
                c--;
            }
            // Increasing the counter
            c++;
        }

        // Returning the correct result
        return l.get(0).getNum();
    }
}

班级一词:

代码语言:javascript
运行
复制
package com.fowlron.calculator;

import java.util.ArrayList;

public class Term {
    // I didn't know what to call this class, specially because I'm not english
    // and didn't know a better name for it. It basically is a class that can
    // hold eigter a String, a Double, or an ArrayList of itself.
    // I make an ArrayList of these, so that I can then loop through it and
    // solve the calculation. The fact it can hold an ArrayList of itself is so
    // that when I implement things like "2*(2+3)" I can store 2+3 as another
    // list, inside the main one. The I'd first find all the lists in the main
    // list, and solve them. I might make the calculate method in the other
    // class recursive for it to call itself, which in my head seems to work,
    // and would help for parenthesis inside parenthesis.
    private Type type;
    private double i;
    private String s;
    private ArrayList<Term> al;

    public Term(double i) {
        this.i = i;
        this.s = null;
        this.al = null;
        this.type = Type.DOUBLE;
    }

    public Term(String s) {
        this.i = -1d;
        this.s = s;
        this.al = null;
        this.type = Type.STRING;
    }

    public Term(ArrayList<Term> al) {
        this.i = -1d;
        this.s = null;
        this.al = al;
        this.type = Type.ARRAYLIST;
    }

    public String getOp() {
        return s;
    }

    public double getNum() {
        return i;
    }

    public ArrayList<Term> getPar() {
        return al;
    }

    public void setOp(String s) {
        this.i = -1d;
        this.s = s;
        this.al = null;
        this.type = Type.STRING;
    }

    public void setNum(double i) {
        this.i = i;
        this.s = null;
        this.al = null;
        this.type = Type.DOUBLE;
    }

    public void setPar(ArrayList<Term> al) {
        this.i = -1d;
        this.s = null;
        this.al = al;
        this.type = Type.ARRAYLIST;
    }

    public Type getType() {
        return type;
    }

    public enum Type {
        DOUBLE, STRING, ARRAYLIST
    }
}
EN

回答 1

Code Review用户

发布于 2015-01-15 00:52:00

我将首先回顾代码的较小部分,如果稍后有时间的话,我将深入研究逻辑.

  • 方法isCharNumber()是多余的,因为已经存在Character.isDigit()
  • 变量声明应该输入为接口,而不是一个具体的类,例如List<Term> list = new ArrayList<>()
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/77552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档