科学计算器(windows标准)—C++&Java

版权声明:就是码字也不容易啊 https://blog.csdn.net/qq_40946921/article/details/84641460

模拟Windows系统自带的标准计算器

完成功能:

         多位数(小数默认最多保留4位小数)加减乘除、括号、取反、退格、CE清空数字、C重置——键盘输入或鼠标点击都可

         开方、求倒未实现(扩展很容易),M系按键未实现(不知道干嘛用的)

         若还存在输入bug,请评论指出=.=,我来修改

运行效果:

实现方式:

    计算器核心:

1、表达式存储->Vector<String>:使用一个动态的字符串数组来存储中缀表达式,为什么不用字符串呢,如果你以前写过计算器或者看过别人写的代码,大多数人写的要么只支持一位数的运算,要么存在很多bug,为什么有这些问题,因为把表达式当成一个字符串的话,数与数之间,数与运算符之间,以及数的检测是个让人很头疼的问题,所以这里才用字符串数组,比如你的表达式是(15+2)*3,那么这个字符串数组应该是{“(”,“15”,“+”,“2”,“)”,“*”,“3”},这样就避免了很多问题

2、表达式转换(中缀->后缀)->trans()函数:使用库中的栈(Stack,Java和C++都有)来进行转换,为什么要转换成后缀表达式呢?是因为电脑并不能识别运算的优先顺序(比如先乘除后加减)、而后缀表达式就是通过比较优先级将得到的,所以计算机如果拿到了后缀表达式,就可以之间运算。

3、表达式运算->counter()函数得到了表达式之后就很容易了,逐个出栈进行运算就行了,但要注意的是除法运算除数不为0;

      图形界面:

            使用javaFx做的界面,细节没什么好说的。

C++:https://blog.csdn.net/qq_40946921/article/details/83353033

           无图形界面,只支持一位数运算,可扩展,因为java的计算器核心代码其实就是从C++这搬过去的,可以看一下java代码的数据类型和counter,trans函数,很容易就能得到C++版本的代码。

Java:

import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javax.xml.soap.Text;
import java.lang.reflect.Array;
import java.text.DecimalFormat;
import java.util.*;
public class Calculate extends Application{
    Vector<String> m_exp=new Vector<>(),p_exp=new Vector<>();  //m_exp[]为中缀表达式字符串数组,p_exp[]为后缀
    GridPane pane =new GridPane();  //网格布局面板
    Pane box=new Pane();            //显示面板
    double result=0;    //运算结果

    //number表示当前数,exp为表达式
    Label number=new Label("0"),exp=new Label();

    //按钮
    Button num[]=new Button[11],operator[]=new Button[4],other[]=new Button[13];

    //按钮text
    String op[]={"+","-","*","/"},ot[]={"MC","MR","MS","M+","M-","←","CE","C","±","√","%","1/x","="},out;

    boolean shift=false,lastIsNumber=false,havePut=true,couldBack=false;

    //面板
    public void loadPane(){
        //创建10个数字键及小数点按钮并绑定事件
        for(int i=0;i<11;i++){
            String tmp;
            if(i<10)
                tmp=String.valueOf(i);
            else
                tmp=".";
            num[i]=new Button(tmp);
            num[i].setMinSize(30,26);
            num[i].setOnMouseClicked(e->putNum(tmp));
        }

        //创建4个运算符按键
        for(int i=0;i<4;i++){
            String tmp=op[i];
            operator[i]=new Button(tmp);
            operator[i].setMinSize(30,26);
            operator[i].setOnMouseClicked(e->{
                putExp(tmp);
            });
        }


        for(int i=0;i<13;i++){
            String tmp=ot[i];
            other[i]=new Button(tmp);
            other[i].setFont(Font.font(9));
            other[i].setMinSize(30,26);
        }

        //other键布局
        for(int i=2;i<4;i++)
            for(int j=0;j<5;j++)
                pane.add(other[(i-2)*5+j],j,i);
        pane.add(other[10],4,4);
        pane.add(other[11],4,5);
        other[12].setMinSize(30,58);
        pane.add(other[12],4,6,1,2);

        //数字键布局
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                pane.add(num[(2-i)*3+j+1],j,i+4);
        pane.add(num[0],0,7,2,1);
        num[0].setMinSize(66,26);
        pane.add(num[10],2,7);

        //4个运算符键布局
        for(int i=0;i<4;i++)
            pane.add(operator[i],3,7-i);

        pane.setPadding(new Insets(15,15,0,15));
        pane.add(box,0,0,6,2);
        pane.setHgap(6);
        pane.setVgap(6);
        pane.setBackground(new Background(new BackgroundFill(Color.rgb(217,228,242),null,null)));       //设置面板背景色
        exp.setMinWidth(170);
        exp.setAlignment(Pos.BASELINE_RIGHT);
        exp.setLayoutY(5);
        number.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR,10));
        number.setMinWidth(170);
        number.setMinHeight(30);
        number.setFont(Font.font("微软雅黑", FontWeight.BOLD, FontPosture.REGULAR,20));        //设置显示数字格式
        number.setLayoutY(20);
        number.setAlignment(Pos.BASELINE_RIGHT);

        Rectangle rectangle =new Rectangle(0,0,173,50);
        rectangle.setFill(Color.WHITE);
        rectangle.setStroke(Color.BLACK);
        rectangle.setStrokeWidth(0.1);
        box.getChildren().add(rectangle);
        box.getChildren().add(number);
        box.getChildren().add(exp);

    }
    //按键事件
    public void loadKey(){
        pane.setOnKeyPressed(e->{
            if(e.getCode()== KeyCode.SHIFT)
                shift=true;
            if(shift){
                if(e.getCode()==KeyCode.DIGIT9) {
                    m_exp.add("(");
                    exp.setText(exp.getText()+"(");
                }
                else if(e.getCode()==KeyCode.DIGIT0) {
                    if(havePut==false)
                        m_exp.add(number.getText());
                    m_exp.add(")");
                    lastIsNumber=false;
                    havePut=true;
                    exp.setText(getExp());
                }
            }
            else{
                switch(e.getCode()){
                    case DIGIT0:case NUMPAD0: putNum("0"); break;
                    case DIGIT1:case NUMPAD1: putNum("1"); break;
                    case DIGIT2:case NUMPAD2: putNum("2"); break;
                    case DIGIT3:case NUMPAD3: putNum("3"); break;
                    case DIGIT4:case NUMPAD4: putNum("4"); break;
                    case DIGIT5:case NUMPAD5: putNum("5"); break;
                    case DIGIT6:case NUMPAD6: putNum("6"); break;
                    case DIGIT7:case NUMPAD7: putNum("7"); break;
                    case DIGIT8:case NUMPAD8: putNum("8"); break;
                    case DIGIT9:case NUMPAD9: putNum("9"); break;
                    case BACK_SPACE:
                        if(number.getText().length()>1)
                            number.setText(number.getText().substring(0,number.getText().length()-1));
                        else{
                            number.setText("0");
                            lastIsNumber=true;
                        }
                        havePut=false;
                        break;

                    case ADD:putExp("+");break;
                    case SUBTRACT:putExp("-");break;
                    case MULTIPLY:putExp("*");break;
                    case DIVIDE:putExp("/"); break;
                    case EQUALS:case ENTER:
                        exp.setText("");
                        if(havePut==false)
                            m_exp.add(number.getText());
                        trans();
                        if(counter()==0)
                            number.setText(String.valueOf(result));
                        else
                            number.setText("除数不能为0");
                        havePut=true;
                        lastIsNumber=true;
                        m_exp.clear();
                        break;
                }
            }
        });
        pane.setOnKeyReleased(e->{if(e.getCode()== KeyCode.SHIFT)
            shift=false;});
    }

    //事件
    public void loadAction(){
        other[5].setOnMouseClicked(e->{
            if(couldBack) {
                if (number.getText().length() > 1)
                    number.setText(number.getText().substring(0, number.getText().length() - 1));
                else {
                    number.setText("0");
                    lastIsNumber = true;
                }
                havePut = false;
            }
        });
        other[6].setOnMouseClicked(e->{number.setText("0");});
        other[7].setOnMouseClicked(e->{m_exp.clear();result=0;havePut=false;lastIsNumber=false;number.setText("0");exp.setText("");});
        other[8].setOnMouseClicked(e->{
            if(number.getText().charAt(0)=='-')
                number.setText(number.getText().substring(1,number.getText().length()));
            else
                number.setText("-"+number.getText());
            havePut=false;
            couldBack=true;
        });
        other[12].setOnMouseClicked(e->{
            exp.setText("");
            if(havePut==false)
                m_exp.add(number.getText());
            trans();
            if(counter()==0)
                number.setText(String.valueOf(result));
            else {
                number.setText("除数不能为0");
                couldBack = false;
            }
            havePut=true;
            lastIsNumber=true;
            m_exp.clear();
        });
    }

    //输入数字
    public void putNum(String str){
            if(havePut||number.getText().equals("0")||(havePut&&number.getText().length()>12))
                if(str.equals("."))
                    number.setText(number.getText()+str);
                else
                    number.setText(str);
            else if(number.getText().length()<=12)
                number.setText(number.getText()+str);
            lastIsNumber=true;
            havePut=false;
            couldBack=true;
    }

    //输入符号
    public void putExp(String str){
        if(lastIsNumber){
            m_exp.add(number.getText());
            trans();
            if(counter()==0) {
                number.setText(String.valueOf(result));
            }
            else {
                number.setText("除数不能为0");
                couldBack=false;
            }

            m_exp.add(str);;
        }
        else if(m_exp.lastElement().equals("(")||m_exp.lastElement().equals(")")){
            m_exp.add(str);
        }
        else {
            m_exp.remove(m_exp.size() - 1);
            m_exp.add(str);
        }

        lastIsNumber=false;
        havePut=true;
        exp.setText(getExp());
    }

    //退格
    public void putBracket(String str){
        if(lastIsNumber){
            m_exp.add(str);
            lastIsNumber=false;
            havePut=true;
            exp.setText(getExp());
        }
    }

    //计算
    int counter(){
        double a,b;
        Stack<Double> stack=new Stack<>();
        for(int i=0;i<p_exp.size();i++){
            if(p_exp.get(i).charAt(0)>='0'&&p_exp.get(i).charAt(0)<='9'||p_exp.get(i).length()>1){
                stack.push(Double.valueOf(p_exp.get(i)));
            }
            else{
                switch (p_exp.get(i)) {
                    case "+":
                        a = stack.pop();
                        b = stack.pop();
                        stack.push(a+b);
                        break;
                    case "*":
                        a = stack.pop();
                        b = stack.pop();
                        stack.push(a*b);
                        break;
                    case "-":
                        a = stack.pop();
                        b = stack.pop();
                        stack.push(b-a);
                        break;
                    case "/":
                        a = stack.pop();
                        b = stack.pop();
                        if(a==0)
                            return 1;
                        stack.push(b/a);
                        break;
                }

            }
        }
        if(stack.size()!=1)
            return 1;
        DecimalFormat df = new DecimalFormat("#.0000");
        result=Double.valueOf(df.format(stack.peek()));
        if(String.valueOf(result).length()>12){
            result=(double)((int)(result/Math.pow(10,String.valueOf(result).length()-12))*Math.pow(10,String.valueOf(result).length()-12));
        }
        return 0;
    }

    Vector<String> trans(){
        p_exp.clear();
        Stack<String> stack=new Stack<>();
        String operators=new String("+-*/(");
        for (int i = 0; i < m_exp.size(); i++) {
            if (operators.indexOf(m_exp.get(i).charAt(0)) != -1&&m_exp.get(i).length()==1) {      //出现操作符
                if (m_exp.get(i).charAt(0) == '(')         //栈中添加左括号
                    stack.push(m_exp.get(i));
                else {                      //操作符的优先级判断
                    while ((!stack.empty()) && (priority(m_exp.get(i).charAt(0)) <= priority(stack.peek().charAt(0)))) {    //当栈不为空时,进行优先级判断
                        p_exp.add(stack.pop());   //若当前操作符优先级低于栈顶,弹出栈顶,放到后缀式中
                    }
                    stack.push(m_exp.get(i));
                }
            }
            else if (m_exp.get(i).charAt(0) == ')') {            //出现右括号时,将栈中元素一直弹出,直至弹出左括号
                while (stack.peek().charAt(0) != '(') {
                    p_exp.add(stack.pop());
                }
                stack.pop();                       //弹出左括号
            }
            else {           //把操作数加入到后缀式中
                p_exp.add(m_exp.get(i));
            }
        }
        while (!stack.empty()) {    //将栈中剩余操作符放到后缀式中
            p_exp.add(stack.pop());
        }
        return p_exp;
    }
    //获取表达式
    String getExp(){
        out=new String();
        for(int j =0;j<m_exp.size();j++){
            out+=m_exp.get(j);
            if(j!=m_exp.size()-1)
                out+=" ";
        }
        if(out.length()>25)
            out="<"+out.substring(out.length()-25);
        return out;
    }

    //获取运算符优先级
    int priority(char ch){
        if (ch == '*'||ch=='/')
            return 2;
        if (ch == '+'||ch=='-')
            return 1;
        if (ch == '(')
            return -1;
        return 0;
    }

    public void start(Stage stage){
        loadPane();
        loadAction();
        loadKey();
        Scene scene=new Scene(pane,195,260);
        stage.setScene(scene);
        stage.setResizable(false);
        stage.setTitle("计算器—Italink");
        stage.show();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40946921/article/details/84641460