每日20行之4~~~两种方法java实现简易计算器 附带复杂计算器代码(优先级顺序)

输入一行算式,每一个数字和运算符用空格隔开,例如“1 + 2 + 3 * 5 = “
其中不存在运算先后顺序,暂且不考虑,每日20行,之后慢慢实现,不可一口吃下一个胖子。 从左到右计算。

1. 第一种解决方法:

package 从零单排学Java;

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

public class SimpleCalculator {
public static void main(String[] args) {
    boolean whethercontinue = true;

    ArrayList formula = new ArrayList();
    while(whethercontinue){
    System.out.println("Enter the formula:");
    Scanner in = new Scanner(System.in);
    String temp = "";
    formula.add(in.next());
    for(int i = 0;i<=formula.size();i++){
    temp = formula.get(i);
    String[] temp1 = temp.split(" ");
    int[] count = null;
    char[] operator = null;
    for(int j = 0;j<(temp.length()/2);j++){
    count = new int[temp.length()/2];
    count[j] = Integer.parseInt(temp1[2*j]);
    operator = new char[temp.length()/2];
    operator[j] = temp1[2*j+1].charAt(0);
    }
    for(int l=0; lif(operator[l]!='='){
        if(operator[l]=='+') count[l+1]+=count[l];
        else if(operator[l]=='-') count[l+1]+=count[l];
        else if(operator[l]=='*') count[l+1]+=count[l];
        else count[l+1]+=count[l];
        }
        else{
            System.out.println("The calculation is finished.");
        }
    }
    System.out.println("The result of the calculation is: "+count[count.length-1]);
    }
    System.out.println("Do you want to continue? If not, please input n.");
    if(in.next()=="n"){
        whethercontinue = false;
    }
}
}
}

2. 第二种解决办法:

 这种办法逻辑更为清晰,并没有用到数组。
package 从零单排学Java;

import java.util.Scanner;
public class Test1{
   public static void main(String []args)
   {
       String s1_1,s1_2,s2;
       Scanner in=new Scanner(System.in);
       s1_1=in.next();
       System.out.println(s1_1);
       System.out.println("----------");
       in.nextLine(); // 把剩余的吃掉
       s2=in.nextLine();
       System.out.println(s2);
       System.out.println("----------");
       s1_1=in.next();
       s1_2=in.next();
       System.out.println(s1_1+"       "+s1_2);
   }
}
-------------------------------------------
 */
package 从零单排学Java;

import java.util.Scanner;
public class Test2{
  public static void main(String args[]) {
       int ri, repeat;
       int op1, op2, res;
       char operator;
       Scanner in=new Scanner(System.in);
       repeat=in.nextInt();
       for(ri=1; ri<=repeat; ri++){
         op1=in.nextInt();
         operator =(in.next()).charAt(0);  //
         res=op1;  //res看作最后的结果
         while(operator!='=')
         {
             op2=in.nextInt();
             if(operator=='+') res+=op2;

3. 复杂计算器的程序留着日后参考

package com.saturday;

import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyParse {
    static Map optrOrder;
    static {
        optrOrder=new HashMap();
        optrOrder.put("(", 0);
        optrOrder.put("*", 1);
        optrOrder.put("/", 1);
        optrOrder.put("%", 1);
        optrOrder.put("+",2);
        optrOrder.put("-",2);
        optrOrder.put("^",3);
        optrOrder.put("#",3);
    }

    public static void main(String[] args){
        List tokens;        
        try{
            //词法分析
            tokens=lex("+2* (-2+3*4)+-5");

            //中缀转后缀            
            tokens=toRpn(tokens);            

            //计算结果
            System.out.println(calcRpn(tokens));

        }catch(Exception ex){
            ex.printStackTrace();
        }        
    }

/**
     * 将输入串转换为操作符串
     * @param sExpres
     * @return
     */
    public static List lex(String sExpres){        
        List tokens=new ArrayList();        

        //将表达式分割成符号序列
        String sRegExp="(((?<=^|\\(|\\+|-|\\*|/|%)(\\+|-))?\\d+(\\.\\d+)?)"
                      +"|\\(|\\)|\\*|/|\\+|-";
        Pattern p=Pattern.compile(sRegExp);
        Matcher m=p.matcher(sExpres.replaceAll("\\s+",""));        
        while(m.find()){
            tokens.add(m.group());
        }

        tokens.add("#");

        return tokens;
    }

    /**
     * 将中缀表单时转化为后缀表达式
     * @param tokens
     * @return
     */
    public static List toRpn(List tokens) 
                                     throws Exception{
        List  rpnList=new ArrayList();
        Stack optrStack=new Stack();

        optrStack.add("^");
        for(String token:tokens){
            if(token.matches("^(\\+|-)?\\d+(\\.\\d+)?$")){
                rpnList.add(token);
            }else{
                outputOptr(token,optrStack,rpnList);
            }
        }    

        if(!optrStack.isEmpty()
           &&optrStack.lastElement().equals("#")){
            return rpnList;
        }else{
            throw new Exception("后缀表达式转化错误!");
        }        
    }

/**
     * 计算后缀表达式的值
     * @param  rpnTokens
     * @return
     * @throws Exception
     */
    public static double calcRpn(List rpnTokens)
                                 throws Exception{
        NumberFormat nf=NumberFormat.getInstance();
        Stack numStack=new Stack();

        for (String token : rpnTokens) {
            if (token.matches("^(\\+|-)?\\d+(.\\d+)?$")) {
                token=token.indexOf('+')==0
                     ?token.substring(1)
                     :token;
                numStack.add(nf.parse(token).doubleValue());
            } else {
                doCalcByOptr(token, numStack);
            }
        }

        if (!numStack.isEmpty() && numStack.size() == 1) {
            return numStack.lastElement();
        } else {
            throw new Exception("计算错误!");
        }
    }    

    /**
     * 将运算符输出到后缀表达式序列.
     * @param optr
     * @param optrStack
     * @param rpnList
     * @throws Exception
     */
    public static void outputOptr(String optr,
                                  Stack optrStack,
                                  List  rpnList) 
                                  throws Exception{
        String preOptr;

        if(optr.equals("(")){//处理左括号
            optrStack.push(optr);
            return;
        }

        if(optr.equals(")")){//处理右括号                    
            while(!optrStack.isEmpty()){
                preOptr=optrStack.pop();
                if(!preOptr.equals("(")){
                    rpnList.add(preOptr);                    
                }else{
                    break;
                }
            }

            if(optrStack.isEmpty()){
                throw new Exception("括号未闭合!");
            }

            return;
        }

        /*按优先级处理其他运算符,若当前运算符优先级较高
         * 直接入栈,否则将栈中运算符出战直至栈顶运算符
         * 低于当前运算符
         */
        preOptr=optrStack.lastElement();
        if(optrCmp(optr,preOptr)<0){
            optrStack.push(optr);
        }else{
            while(!preOptr.equals("(")
                 &&!optrStack.isEmpty()
                 &&optrCmp(optr,preOptr)>=0){

                 preOptr=optrStack.pop();
                 if(!preOptr.equals("^")){
                     rpnList.add(preOptr);
                 }     
            }
            optrStack.push(optr);
        }        
    }

/**
     * 运算符优先级比较函数,optr1优先级大于optr2返回小于0值,
     * 优先级相等返回0,optr1小于optr2返回大于0值.
     * @param optr1
     * @param optr2
     * @return
     */
    public static int optrCmp(String optr1,String optr2){
        int order1=optrOrder.get(optr1);
        int order2=optrOrder.get(optr2);
        return order1-order2;
    }

/**
     * 根据运算符对数据栈中的内容进行操作.
     * @param optr
     * @param numStack
     */
    public static void  doCalcByOptr(String optr,
                                     Stack numStack){
        double n1,n2;
        n2=numStack.pop();
        n1=numStack.pop();

        if(optr.equals("+")){
            numStack.push(n1+n2);
        }else if(optr.equals("-")){
            numStack.push(n1-n2);
        }else if(optr.equals("*")){
            numStack.push(n1*n2);
        }else if(optr.equals("/")){
            numStack.push(n1/n2);
        }else if(optr.equals("%")){
            numStack.push(n1%n2);
        }
    }
}

你可能感兴趣的:(从零单排学编程之每日20行)