簡體   English   中英

具有多種操作的 Java 計算器

[英]Java calculator with multiple operations

到目前為止,我有以下工作正常。 我確信可能有一種更簡單的方法可以做到這一點,但我需要改變/改變的是 Matheq 的頂級方法。 Math 方法執行單個數學運算。

它適用於 +、-、* 和 / 的任何單個操作。

我的問題是求解一個更大的方程,例如 10 - 10 / 5 + 3。但是它確實可以正確求解 10 / 5 + 65 * 2。 原因是每個部分,數字和操作,都被拆分為一個字符串數組。 每次操作完成后,數字和操作將替換為該等式的結果。 可能看起來更混亂,但我想不出更好的方法。 它無法解決其他方程的原因是因為我如何將字符串映射回字符串數組。

字符串數組示例 Ex. 與 10 - 10 / 5 + 3 String = { 10, -, 10, /, 5, +, 3 } 運算后先除法然后從左到右減法然后加法 String = { 8, 8, 2, 2, 2, 5, 5 }

這是我的代碼,請有人幫助我:

REVISED已修改,現在它可以與上面一起使用,但對於 LONG 方程仍然存在一些問題。 一個簡短的例子是它可以很好地解決 2 * 2 * 2 * 2 除以 5 但如果將其更改為 10 - 2 * 2 * 2 * 2 除以 5 我會得到錯誤的答案。

 public class Matheq {

String fnum = null;
String lnum = null;
String total = null;

public String Matheq(String mathoperation) {

    String mathoperation= "6 * 3 - 4 * 2";

    mathoperation = mathoperation.replaceAll(",", "");
    mathoperation = mathoperation.replaceAll("plus", "+");
    mathoperation = mathoperation.replaceAll("minus", "-");
    mathoperation = mathoperation.replaceAll("times", "*");
    mathoperation = mathoperation.replaceAll("divided by", "dividedby");
    mathoperation = mathoperation.replaceAll("percent of", "percentof");
    String[] splitstr = mathoperation.split(" ");
    while(splitstr.length>1){
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("percentof") >= 0) {
        String buildit = splitstr[i-1] + " percent of " + splitstr[i+1];
        String done = math(buildit);
        System.out.println("Percentage operation: " + splitstr[i-1] + " percent of " + splitstr[i+1] + "=" + done);
        splitstr[i] = done;
        splitstr[i-1] = "";
        splitstr[i+1] = "";
        ArrayList<String> list = new ArrayList<String>();
        for(String s : splitstr){
            if(!s.equals("")){
                list.add(s);
            }
        }
        splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("dividedby") >= 0) {
            String buildit = splitstr[i-1] + " divided by " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Division operation: " + splitstr[i-1] + " divided by " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
        System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("*") >= 0) {
            String buildit = splitstr[i-1] + " * " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Multiplication operation: "+ splitstr[i-1] + " * " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
    for(int i=0; i<splitstr.length; i++) {
            System.out.println("Get value: " + splitstr[i]);
        if(splitstr[i].indexOf("+") >= 0) {
            String buildit = splitstr[i-1] + " + " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Addition operation: " + splitstr[i-1] + " + " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }
    }
        for(int i=0; i<splitstr.length; i++) {
            System.out.println("Get value: " + splitstr[i]);
            if(splitstr[i].indexOf("-") >= 0) {
            String buildit = splitstr[i-1] + " - " + splitstr[i+1];
            String done = math(buildit);
            System.out.println("Subtraction operation: " + splitstr[i-1] + " - " + splitstr[i+1] + "=" + done);
            splitstr[i] = done;
            splitstr[i-1] = "";
            splitstr[i+1] = "";
            ArrayList<String> list = new ArrayList<String>();
            for(String s : splitstr){
                if(!s.equals("")){
                    list.add(s);
                }
            }
            splitstr = list.toArray(new String[list.size()]);
        }   
    }
    for(int i=0; i<splitstr.length; i++) {  
        System.out.println("Final operation: " + total + " " + splitstr[i]);
    }
    }
    return total;

}

private String math(String mathoperation) {
    // TODO Auto-generated method stub
    if(mathoperation.contains("percent of")){
        mathoperation = mathoperation.replaceAll("percent of", "%");
        int str = mathoperation.indexOf("%");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        fnum = "." + fnum;
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intlnum * intfnum;
        System.out.println(tot);
        total = Double.toString(tot);
        if(total.length() == 3){
            total = total + "0";
        }
        if(total.length() > 5){
            total = total.substring(0, 4);
        }
        total = total.replace("0.", "");
        System.out.println("Total:" + total);
        } else 
    if(mathoperation.contains("-")){
        int str = mathoperation.indexOf("-");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intfnum - intlnum; 
        System.out.println(tot);
        total = Double.toString(tot);
        System.out.println(total);
        } else 
    if(mathoperation.contains("+")){
        int str = mathoperation.indexOf("+");
        System.out.println(str);
        fnum = mathoperation.substring(0, str-1);
        fnum = fnum.replaceAll(" ", "");
        System.out.println(fnum);
        double intfnum = Double.parseDouble(fnum);
        System.out.println(intfnum);
        int lastind = mathoperation.length();
        System.out.println(lastind);
        lnum = mathoperation.substring(str+1, lastind);
        lnum = lnum.replaceAll(" ", "");
        System.out.println(lnum);
        double intlnum = Double.parseDouble(lnum);
        System.out.println(intlnum);
        double tot = intfnum + intlnum; 
        System.out.println(tot);
        total = Double.toString(tot);
        System.out.println(total);
        } else 
    if(mathoperation.contains("*")){
    int str = mathoperation.indexOf("*");
    System.out.println(str);
    fnum = mathoperation.substring(0, str-1);
    fnum = fnum.replaceAll(" ", "");
    System.out.println(fnum);
    double intfnum = Double.parseDouble(fnum);
    System.out.println(intfnum);
    int lastind = mathoperation.length();
    System.out.println(lastind);
    lnum = mathoperation.substring(str+1, lastind);
    lnum = lnum.replaceAll(" ", "");
    System.out.println(lnum);
    double intlnum = Double.parseDouble(lnum);
    System.out.println(intlnum);
    double tot = intfnum * intlnum; 
    System.out.println(tot);
    total = Double.toString(tot);
    System.out.println(total);
    } else
    if(mathoperation.contains("divided by")){
    mathoperation = mathoperation.replaceAll("divided by", "/");
    int str = mathoperation.indexOf("/");
    System.out.println(str);
    fnum = mathoperation.substring(0, str-1);
    fnum = fnum.replaceAll(" ", "");
    System.out.println(fnum);
    double intfnum = Double.parseDouble(fnum);
    System.out.println(intfnum);
    int lastind = mathoperation.length();
    System.out.println(lastind);
    lnum = mathoperation.substring(str+1, lastind);
    lnum = lnum.replaceAll(" ", "");
    System.out.println(lnum);
    double intlnum = Double.parseDouble(lnum);
    System.out.println(intlnum);
    double tot = intfnum / intlnum; 
    System.out.println(tot);
    total = Double.toString(tot);
    System.out.println(total);
    } else {
        total = null;
    }
    return total;
}

}

數組是表示解析方程的錯誤結構。 您需要有一個可以表示運算符優先級的結構。 處理這類問題的典型機制是抽象語法樹 對於您的 10 - 10 / 5 + 3 示例,您可能希望構建一個如下所示的樹:

 <result>
  /   \
 '-' '+'
 / \ / \
10 '/'  3
   / \
  10  5

使用這種具有高優先級運算符的結構在樹的下方,您可以執行自下而上的評估以獲得正確的結果。

您所要做的就是將前綴輸入轉換為后綴格式。 然后,您可以使用堆棧輕松完成魔術。 我已經使用命令模式編寫了一個完整的解決方案。

將中綴轉換為后綴的方法

    public static List<String> infixToPostfixConvert(String input) {

    int priority = 0;
    String postfixBuffer = "";
    Stack<Character> stack = new Stack<Character>();
    List<String> postfixArray = new ArrayList<String>();

    for (int i = 0; i < input.length(); i++) {
        char ch = input.charAt(i);
        if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {

            if (postfixBuffer.length() > 0) {
                postfixArray.add(postfixBuffer);
            }
            postfixBuffer = "";
            // check the precedence
            if (stack.size() <= 0)
                stack.push(ch);
            else {
                Character chTop = (Character) stack.peek();
                if (chTop == '*' || chTop == '/')
                    priority = 1;
                else
                    priority = 0;
                if (priority == 1) {
                    if (ch == '+' || ch == '-') {
                        postfixArray.add(String.valueOf(stack.pop()));
                        i--;
                    } else { // Same
                        postfixArray.add(String.valueOf(stack.pop()));
                        i--;
                    }
                } else {
                    if (ch == '+' || ch == '-') {
                        postfixArray.add(String.valueOf(stack.pop()));
                        stack.push(ch);
                    } else
                        stack.push(ch);
                }
            }
        } else {
            postfixBuffer += ch;
        }
    }
    postfixArray.add(postfixBuffer);
    int len = stack.size();
    for (int j = 0; j < len; j++)
        postfixArray.add(stack.pop().toString());

    return postfixArray;
}

然后我有另一種使用計算器實例並傳遞后綴字符串的方法。

    public void calculate(Calculator cal, List<String> postFix) {

    Stack<BigDecimal> stack = new Stack<BigDecimal>();

    for ( int i = 0; i < postFix.size(); i++ ) {

        String next = postFix.get(i);

        if (next.equals("+") || next.equals("-") || next.equals("*")
                || next.equals("/")) {
            ArithmaticCalculatorCommand cmd = new ArithmaticCalculatorCommand(
                    next.charAt(0), stack.pop(), stack.pop(), cal);
            Invoker invoker = new Invoker();
            invoker.compute(cmd);
            stack.push(cal.getCurrent());
        } else if ( false ){

        }
        else
        {
            stack.push(new BigDecimal(next.trim()));
        }
    }
}

完成實施

命令接口

package org.sanjaya;
public interface Command {

    public void calculate();
}

命令實現

package org.sanjaya.impl;

import java.math.BigDecimal;

import org.sanjaya.Command;

public class ArithmaticCalculatorCommand implements Command {

    private char operator;
    private BigDecimal leftOperand;
    private BigDecimal rightOperand;
    private Calculator calculator;

    public ArithmaticCalculatorCommand( char operator, BigDecimal leftOperand, BigDecimal rightOperand, Calculator calculator ) {
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
        this.operator = operator;
        this.calculator = calculator;
    }

    /*
     * This method invoke the three argument operation method that is only used for arithmetic calculations.
     * @param operator
     * @param leftOperand
     * @param rightOperand   * 
     * @see org.sanjaya.Command#calculate()
     */
    public void calculate() {
        calculator.operation( operator, leftOperand, rightOperand );        
    }   
}

計算器類(接收者)

package org.sanjaya.impl;

import java.math.BigDecimal;

public class Calculator {

    private static Calculator calculator;   
    private BigDecimal current = new BigDecimal( 0 );

    private Calculator()
    {

    }

    public static Calculator getInstance()
    {
        if ( calculator == null )
        {
            calculator = new Calculator();
        }
        return calculator;
    }

    /*
     * This method calculate current value for any number of calculation operations.
     * Currently following operations are supported
     * +,-,*,/
     * 
     * @param operator
     * @param leftOperand
     * @param rightOperand
     *  
     */
    public void operation( char operator, BigDecimal leftOperand, BigDecimal rightOperand )
    {       
        switch ( operator )
        {
        case '+':
            current = leftOperand.add( rightOperand );
            break;
        case '-':
            current = rightOperand.subtract( leftOperand );
            break;
        case '/':
            current = rightOperand.divide(leftOperand);
            break;
        case '*':
            current = leftOperand.multiply( rightOperand );
            break;
        default:
            break;
        }       
    }

    public BigDecimal getCurrent() {
        return current;
    }

    public void setCurrent(BigDecimal current) {
        this.current = current;
    }

}

調用者類

package org.sanjaya.impl;

import java.math.BigDecimal;

import org.sanjaya.Command;
public class Invoker {

    public void compute( Command command )
    {
        command.calculate();
    }   
}

客戶端類

package org.sanjaya.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.logging.Logger;
public class CalculatorParser {

    public static Logger logger = Logger.getLogger( "Calculator_Logger" );

    public static void main( String a [] )
    {
        new CalculatorParser().start();
    }

    /*
     * This is the starting point of the program. It receives input from the command line 
     * and process them further and sends to calculate function. At the end this method 
     * displays the calculated result.
     */
    public void start()
    {
        Scanner scanner = new Scanner( System.in );
        logger.info("\n\t Please input expression to calculate::");

        String line = scanner.nextLine();
        List<String> postfixString = CalculatorParser.infixToPostfixConvert( line );
        Calculator calculator = Calculator.getInstance();
        calculator.setCurrent( new BigDecimal( 0 ) );

        calculate( calculator, postfixString );

        logger.info("Result is " + calculator.getCurrent() );
    }

    /*
     * This method keeps a stack to process postfix version of the input and execute the right command implementation.
     * Currently this method supports for arithmetic command calculations only.
     * @param Cal
     * @param postFix
     */
    public void calculate(Calculator cal, List<String> postFix) {

        Stack<BigDecimal> stack = new Stack<BigDecimal>();

        for ( int i = 0; i < postFix.size(); i++ ) {

            String next = postFix.get(i);

            if (next.equals("+") || next.equals("-") || next.equals("*")
                    || next.equals("/")) {
                ArithmaticCalculatorCommand cmd = new ArithmaticCalculatorCommand(
                        next.charAt(0), stack.pop(), stack.pop(), cal);
                Invoker invoker = new Invoker();
                invoker.compute(cmd);
                stack.push(cal.getCurrent());
            } else if ( false ){

            }
            else
            {
                stack.push(new BigDecimal(next.trim()));
            }
        }
    }

    /*
     * This method convert the infix into postfix in order to proceed in the calculation.
     * @param input 
     */
    public static List<String> infixToPostfixConvert(String input) {

        int priority = 0;
        String postfixBuffer = "";
        Stack<Character> stack = new Stack<Character>();
        List<String> postfixArray = new ArrayList<String>();

        for (int i = 0; i < input.length(); i++) {
            char ch = input.charAt(i);
            if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {

                if (postfixBuffer.length() > 0) {
                    postfixArray.add(postfixBuffer);
                }
                postfixBuffer = "";
                // check the precedence
                if (stack.size() <= 0)
                    stack.push(ch);
                else {
                    Character chTop = (Character) stack.peek();
                    if (chTop == '*' || chTop == '/')
                        priority = 1;
                    else
                        priority = 0;
                    if (priority == 1) {
                        if (ch == '+' || ch == '-') {
                            postfixArray.add(String.valueOf(stack.pop()));
                            i--;
                        } else { // Same
                            postfixArray.add(String.valueOf(stack.pop()));
                            i--;
                        }
                    } else {
                        if (ch == '+' || ch == '-') {
                            postfixArray.add(String.valueOf(stack.pop()));
                            stack.push(ch);
                        } else
                            stack.push(ch);
                    }
                }
            } else {
                postfixBuffer += ch;
            }
        }
        postfixArray.add(postfixBuffer);
        int len = stack.size();
        for (int j = 0; j < len; j++)
            postfixArray.add(stack.pop().toString());

        return postfixArray;
    }
}

我沒有讓點工作,那是另一天。

mainlaunch讓按鈕將它們的文本發送到我們的 buttonHandler。

buttons.get(i).setOnAction(ev -> buttonHandler(text))

在方法中:

  • 如果該文本是一個數字,只需附加它。
  • 如果它是運算符,則將其添加到堆棧中。
  • 如果堆棧上有 * 或 / 則執行計算並將新數字添加到堆棧中。
  • 最后只有 + 和 - 在堆棧上
  • 計算結果。

編碼:

private void buttonHandler(String buttonValue) {
    String newInput = tfInput.getText();

    switch (buttonValue) {
        default:
            // If a previous calculation was made, reset input.
            if (lastOperator.equals("=")) {
                lInput.setText("");
                tfInput.setText(buttonValue);

            // else append the new input.
            } else {
                tfInput.appendText(buttonValue);
            }
            break;
        case " ":
            break;
        case ".":
            if(!input.contains(".")) {
                tfInput.appendText(buttonValue);
            }
            break;
        case "DEL":
            try {
                tfInput.setText("" + newInput.substring(0, tfInput.getText().length() - 1));
            } catch (Exception ex) { }
            break;

        // Operators
        case "x":
        case "/":
        case "+":
        case "-":
        case "=":

            if (newInput.length() > 0) {
                lInput.setText(lInput.getText() + newInput + " " + buttonValue + " ");

                try {
                    // If the previous operator has priority, make a calculation and push to stack
                    if (!input.empty()) {
                        if (input.peek().equals("x")) {
                            input.pop();
                            newInput = new BigDecimal(input.pop()).multiply(new BigDecimal(newInput)).toString();
                        } else if (input.peek().equals("/")) {
                            input.pop();
                            newInput = new BigDecimal(input.pop()).divide(new BigDecimal(newInput), 3, RoundingMode.HALF_UP).stripTrailingZeros().toString();
                            System.out.println(newInput);
                        }
                    }
                } catch (Exception ex) {
                    System.out.println("something is this part went wrong");
                }

                // If the "=" wasn't pressed, add input to the stack and set the textfield empty.
                if (!buttonValue.equals("=")) {
                    // Push to stack and empty input.
                    input.push(newInput);
                    input.push(buttonValue);
                    tfInput.setText("");

                // The button is "=". Prepare for final calculation
                } else {
                    if(!input.empty()) {
                        try {
                            // Reverse items.
                            Stack<String> stack = new Stack<>();
                            stack.push(newInput);
                            while (!input.empty()) {
                                stack.push(input.pop());
                            }

                            // Perform final calculation.
                            while (!stack.empty()) {
                                String firstNumber = stack.pop();
                                if (stack.peek().equals("+")) {
                                    stack.pop();
                                    newInput = new BigDecimal(firstNumber).add(new BigDecimal(stack.pop())).toString();
                                } else if (stack.peek().equals("-")) {
                                    stack.pop();
                                    newInput = new BigDecimal(firstNumber).subtract(new BigDecimal(stack.pop())).toString();
                                }
                                if (!stack.empty()) {
                                    stack.push(newInput);
                                } else {
                                    tfInput.setText(newInput);
                                }
                            }

                        } catch (Exception ex) {
                            System.out.println("something in the second part went wrong");
                        }
                    } else {
                        tfInput.setText(newInput);
                    }
                }
            }
    }
    lastOperator = buttonValue;
}

如果您想計算一個字符串,請在“啟動”方法中添加如下內容:

 String test = "10-10/5+3=";
    for (int i = 0; i < test.length(); i++) {
        buttonHandler(test.charAt(i) + "");
    }

// 這個類將使用多個運算符計算數字

包 com.jhunrel25.calculatorproject

導入 java.math。 ; 導入 java.util。 ;

類計算器 { 私有靜態字符串字符串參數;

Calculator(String calculateStringParameter) {
    stringParameter =
        calculateStringParameter.
        replaceAll("(?<=[\\d])(?=[*/+-])", " ").
        replaceAll("(?<=[*/+-])(?=[\\d])", " ");
}
public static String results() {

    Scanner scanner = new Scanner(stringParameter);

    LinkedList<String> data = new LinkedList<String>();
    while (scanner.hasNext()) {
        data.add(scanner.next());
    }
    do {

        // multiplication
        if (data.get(1).equals("*")) {

            BigDecimal x = new BigDecimal(data.get(0));
            BigDecimal y = new BigDecimal(data.get(2));

            data.set(0, (x.multiply(y).toString()));
            data.remove(1);
            data.remove(1);


            // division
        } else if (data.get(1).equals("/")) {

            BigDecimal x = new BigDecimal(data.get(0));
            BigDecimal y = new BigDecimal(data.get(2));

            if (Double.parseDouble(data.get(0)) < 1 || Double.parseDouble(data.get(2)) < 1) {
                return "Divided by 0 Situation.";

            } else if (Double.parseDouble(data.get(0)) < Double.parseDouble(data.get(2))) {
                return "Dividend must be larger than Divisor.";

            } else {

                data.set(0, (x.divide(y).toString()));
                data.remove(1);
                data.remove(1);
            }

            // addition
        } else if (data.get(1).equals("+")) {

            BigDecimal x = new BigDecimal(data.get(0));
            BigDecimal y = new BigDecimal(data.get(2));

            data.set(0, (x.add(y).toString()));
            data.remove(1);
            data.remove(1);


            // subtraction
        } else if (data.get(1).equals("-")) {

            BigDecimal x = new BigDecimal(data.get(0));
            BigDecimal y = new BigDecimal(data.get(2));

            data.set(0, (x.subtract(y).toString()));
            data.remove(1);
            data.remove(1);
        }

    } while (data.size() != 1);
    return data.get(0);
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM