프로그래밍/Java

[JAVA/자바] 공학용계산기 만들기

자바조아! 2021. 1. 14. 00:41

 

1. 소스코드

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import javax.swing.*;
import java.text.DecimalFormat;
import java.util.*;


public class MyApp extends Application {

   // 연산스택
   Stack<String> stack = new Stack<>();
   // 결과
   List<String> result = new ArrayList<>();
   // 출력
   List<String> output = new ArrayList<>();
   // 계산 화면
   TextArea txtA;

   @Override
   public void start(Stage primaryStage) throws Exception {
      primaryStage.setTitle("19m3283");
      primaryStage.setWidth(270);
      primaryStage.setHeight(410);



      MenuBar mBar = new MenuBar();
      Menu mFile = new Menu("ファイル");
      MenuItem miOpen = new MenuItem("開く");
      MenuItem miExit = new MenuItem("終了");
      mFile.getItems().add(miOpen);
      mFile.getItems().add(miExit);
      mBar.getMenus().add(mFile);
      BorderPane root = new BorderPane();
      root.setTop(mBar);


      VBox vbox = new VBox();
      txtA = new TextArea("");
      txtA.setPrefHeight(100);
      VBox.setMargin(txtA, new Insets(3,3, 0, 3));

      HBox hbox = new HBox();
      Button bt = new Button("sin");
      bt.setPrefSize(60, 35);
      HBox.setMargin(bt, new Insets(3,3, 3, 3));
      Button bt1 = new Button("cos");
      bt1.setPrefSize(60, 35);
      HBox.setMargin(bt1, new Insets(3, 0, 3, 0));
      Button bt2 = new Button("tan");
      bt2.setPrefSize(60, 35);
      HBox.setMargin(bt2, new Insets(3, 3, 3, 3));
      Button bt3 = new Button("削除");
      bt3.setPrefSize(60, 35);
      HBox.setMargin(bt3, new Insets(3, 3, 3, 0));
      root.setBottom(hbox);
      hbox.getChildren().addAll(bt,bt1,bt2,bt3);

      HBox hbox1 = new HBox();
      Button bt4 = new Button("指数");
      bt4.setPrefSize(60, 35);
      HBox.setMargin(bt4, new Insets(0, 3,3, 3));
      Button bt5 = new Button("log");
      bt5.setPrefSize(60, 35);
      HBox.setMargin(bt5, new Insets(0, 0, 3, 0));
      Button bt6 = new Button("剰余");
      bt6.setPrefSize(60, 35);
      HBox.setMargin(bt6, new Insets(0, 3, 3, 3));
      Button bt7 = new Button("√");
      bt7.setPrefSize(60, 35);
      HBox.setMargin(bt7, new Insets(0, 3, 3, 0));
      root.setBottom(hbox1);
      hbox1.getChildren().addAll(bt4,bt5,bt6,bt7);

      HBox hbox2 = new HBox();
      Button bt8 = new Button("1/X");
      bt8.setPrefSize(60, 35);
      HBox.setMargin(bt8, new Insets(0, 3,3, 3));
      Button bt9 = new Button("CE");
      bt9.setPrefSize(60, 35);
      HBox.setMargin(bt9, new Insets(0, 0,3, 0));
      Button bt10 = new Button("C");
      bt10.setPrefSize(60, 35);
      HBox.setMargin(bt10, new Insets(0, 0,3, 3));
      Button bt11 = new Button("/");
      bt11.setPrefSize(60, 35);
      HBox.setMargin(bt11, new Insets(0, 3,3, 3));
      root.setBottom(hbox2);
      hbox2.getChildren().addAll(bt8,bt9,bt10,bt11);

      HBox hbox3 = new HBox();
      Button bt12 = new Button("1");
      bt12.setPrefSize(60, 35);
      bt12.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt12, new Insets(0, 3,3, 3));
      Button bt13 = new Button("2");
      bt13.setPrefSize(60, 35);
      bt13.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt13, new Insets(0, 3,3, 0));
      Button bt14 = new Button("3");
      bt14.setPrefSize(60, 35);
      bt14.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt14, new Insets(0, 3,3, 0));
      Button bt15 = new Button("x");
      bt15.setPrefSize(60, 35);
      HBox.setMargin(bt15, new Insets(0, 3,3, 0));
      root.setBottom(hbox3);
      hbox3.getChildren().addAll(bt12,bt13,bt14,bt15);

      HBox hbox4 = new HBox();
      Button bt16 = new Button("4");
      bt16.setPrefSize(60, 35);
      bt16.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt16, new Insets(0, 3,3, 3));
      Button bt17 = new Button("5");
      bt17.setPrefSize(60, 35);
      bt17.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt17, new Insets(0, 0,3, 0));
      Button bt18 = new Button("6");
      bt18.setPrefSize(60, 35);
      bt18.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt18, new Insets(0, 0,3, 3));
      Button bt19 = new Button("ㅡ");
      bt19.setPrefSize(60, 35);
      HBox.setMargin(bt19, new Insets(0, 0,3, 3));
      root.setBottom(hbox4);
      hbox4.getChildren().addAll(bt16,bt17,bt18,bt19);

      HBox hbox5 = new HBox();
      Button bt20 = new Button("7");
      bt20.setPrefSize(60, 35);
      bt20.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt20, new Insets(0, 3,3, 3));
      Button bt21 = new Button("8");
      bt21.setPrefSize(60, 35);
      bt21.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt21, new Insets(0, 3,3, 0));
      Button bt22 = new Button("9");
      bt22.setPrefSize(60, 35);
      bt22.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt22, new Insets(0, 3,3, 0));
      Button bt23 = new Button("+");
      bt23.setPrefSize(60, 35);
      HBox.setMargin(bt23, new Insets(0, 3,3, 0));
      root.setBottom(hbox5);
      hbox5.getChildren().addAll(bt20,bt21,bt22,bt23);

      HBox hbox6 = new HBox();
      Button bt24 = new Button("+/ㅡ");
      bt24.setPrefSize(60, 35);
      bt24.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt24, new Insets(0, 0,3, 3));
      Button bt25 = new Button("0");
      bt25.setPrefSize(60, 35);
      bt25.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt25, new Insets(0, 0,3, 3));
      Button bt26 = new Button(".");
      bt26.setPrefSize(60, 35);
      bt26.setStyle("-fx-border-color: GRAY;-fx-border-width: 1px;-fx-background-color : WHITE");
      HBox.setMargin(bt26, new Insets(0, 0,3, 3));
      Button bt27 = new Button("=");
      bt27.setPrefSize(60, 35);
      HBox.setMargin(bt27, new Insets(0, 0,3, 3));
      root.setBottom(hbox6);
      hbox6.getChildren().addAll(bt24,bt25,bt26,bt27);


      root.setCenter(vbox);
      vbox.getChildren().addAll(txtA,hbox,hbox1,hbox2,hbox3,hbox4,hbox5,hbox6);


      Scene scene = new Scene(root);
      primaryStage.setScene(scene);
      primaryStage.show();

      //Stack 내에 있을 때 연산자 우선순위 : 낮->높
      HashMap<String, Integer> inP = new HashMap<String, Integer>();
      inP.put("(", 0); // 왼쪽 괄호는 스택 내에 있을 땐 우선순위 제일 낮음
      inP.put("+", 1); // 따라서 어떤 연산자든 위에 쌓일 수 있음
      inP.put("-", 1);
      inP.put("*", 2);
      inP.put("/", 2);

      //Stack 밖에서의 연산자 우선순위 : 낮->높
      HashMap<String, Integer> outP = new HashMap<String, Integer>();
      outP.put("+", 1);
      outP.put("-", 1);
      outP.put("*", 2);
      outP.put("/", 2);
      outP.put("(", 3);


      // [C]
      bt10.setOnAction(event -> {
         txtA.setText("");
      });
      // [CE]
      bt9.setOnAction(event -> {
         String v  = txtA.getText();
         if( v .length() != 0){
            txtA.setText(v.substring(0, v.length() - 1));
         }
      });
      // [/]
      bt11.setOnAction(event -> {
         txtA.setText(txtA.getText() + "/");
      });
      // [1]
      bt12.setOnAction(event -> {
         txtA.setText(txtA.getText() + "1");
      });
      // [2]
      bt13.setOnAction(event -> {
         txtA.setText(txtA.getText() + "2");
      });
      // [3]
      bt14.setOnAction(event -> {
         txtA.setText(txtA.getText() + "3");
      });
      // [*]
      bt15.setOnAction(event -> {
         txtA.setText(txtA.getText() + "*");
      });
      // [4]
      bt16.setOnAction(event -> {
         txtA.setText(txtA.getText() + "4");
      });
      // [5]
      bt17.setOnAction(event -> {
         txtA.setText(txtA.getText() + "5");
      });
      // [6]
      bt18.setOnAction(event -> {
         txtA.setText(txtA.getText() + "6");
      });
      // [-]
      bt19.setOnAction(event -> {
         txtA.setText(txtA.getText() + "-");
      });
      // [7]
      bt20.setOnAction(event -> {
         txtA.setText(txtA.getText() + "7");
      });
      // [8]
      bt21.setOnAction(event -> {
         txtA.setText(txtA.getText() + "8");
      });
      // [9]
      bt22.setOnAction(event -> {
         txtA.setText(txtA.getText() + "9");
      });
      // [+]
      bt23.setOnAction(event -> {
         txtA.setText(txtA.getText() + "+");
      });
      // [0]
      bt25.setOnAction(event -> {
         txtA.setText(txtA.getText() + "0");
      });
      // [.]
      bt26.setOnAction(event -> {
         txtA.setText(txtA.getText() + ".");
      });
      // [sin]
      bt.setOnAction(event -> {
         txtA.setText(txtA.getText() + "sin");
      });

      // [tan]
      bt2.setOnAction(event -> {
         txtA.setText(txtA.getText() + "tan");
      });

      // [cos]
      bt1.setOnAction(event -> {
         txtA.setText(txtA.getText() + "cos");
      });
      // [削除] 삭제
      bt3.setOnAction(event -> {
         String v  = txtA.getText();
         if( v .length() != 0){
            txtA.setText(v.substring(0, v.length() - 1));
         }
      });

      // [指数] 지수
      bt4.setOnAction(event -> {
         txtA.setText(txtA.getText() + "e^");
      });

      // [剰余] 거듭제곱
      bt6.setOnAction(event -> {
         txtA.setText(txtA.getText() + "^");
      });
      // [√] 루트
      bt7.setOnAction(event -> {
         txtA.setText(txtA.getText() + "√");
      });

      // [1/X] 역수
      bt8.setOnAction(event -> {
         String v = txtA.getText();
         txtA.setText("1/("+ v +")");
      });

      // [+/-] 루트
      bt24.setOnAction(event -> {
         String v = txtA.getText();
         txtA.setText("-1*("+ v +")");
      });

      // [=]
      bt27.setOnAction(event -> {

         try {

            result.clear();
            output.clear();

            StringBuffer buffer = new StringBuffer();
            String expression = txtA.getText();


            for( int i = 0; i  < expression.length() ; i++) {
               String c = String.valueOf(expression.charAt(i));

               if ("+".equals(c) || "-".equals(c) || "*".equals(c) || "/".equals(c)) {
                  String v = Calculate(buffer.toString());
                  result.add(v);
                  result.add(c);
                  buffer.setLength(0);
               } else if ("(".equals(c) || ")".equals(c)){
                  result.add(c);
               }else{
                  buffer.append(c);
               }
            }

            if( buffer.length() != 0 )  {
               String v = Calculate(buffer.toString());
               result.add(v);
               buffer.setLength(0);
            }


            StringTokenizer st = new StringTokenizer(String.join(" ", result));
            while(st.hasMoreTokens()) {
               String token = st.nextToken();
               if(token.equals("(") || token.equals("/") || token.equals("*") || token.equals("-") || token.equals("+")) {

                  //스택이 비어있으면
                  if(stack.isEmpty()) {
                     stack.push(token);

                     //스택 비어있지 않으면
                  }else {

                     // 우선순위 : top < token
                     if(inP.get(stack.peek()) < outP.get(token)) {
                        stack.push(token);

                     }else {
                        // 우선순위 : top > token
                        while(true) {
                           if(inP.get(stack.peek()) <= outP.get(token)) {
                              stack.push(token);
                              break;
                           } // 우선순위 : top < token 될때까지 Stack pop
                           output.add(stack.pop());
                        }
                     }

                  }
                  // 토큰이 오른쪽 괄호
               } else if(token.equals(")")) {
                  while(true) {
                     if(stack.peek().equals("(")) {
                        stack.pop();
                        break;
                     }
                     output.add(stack.pop());
                  }

                  // 토큰이 숫자
               } else {
                  output.add(token);
               }
            }
            if(!st.hasMoreTokens()) {
               while(true) {
                  if(stack.isEmpty()) {
                     break;
                  }

                  output.add(stack.pop());
               }
            }


            int len = output.size();
            Stack<Double> sum =  new Stack<Double>();

            int i=0;
            while(i<len) {

               if(output.get(i).equals("+")) {
                  double p; double q;
                  q = sum.pop();
                  p = sum.pop();
                  sum.add(p+q);

               }else if(output.get(i).equals("-")) {
                  double p; double q;
                  if( sum.size() == 1){
                     q = sum.pop();
                     sum.add(-1*q);
                  }else{
                     q = sum.pop();
                     p = sum.pop();
                     sum.add(p-q);
                  }
               }else if(output.get(i).equals("*")) {
                  double p; double q;
                  q = sum.pop();
                  p = sum.pop();
                  sum.add(p*q);

               }else if(output.get(i).equals("/")) {
                  double p; double q;
                  q = sum.pop();
                  p = sum.pop();
                  sum.add(p/q);

               }else {
                  sum.add(Double.parseDouble(output.get(i)));

               }

               i++;
            }

            Double s = sum.pop();
            DecimalFormat df=new DecimalFormat("#.###############");
            txtA.setText(df.format(s));

         } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "수식이 올바른지 확인해주세요.");
            e.printStackTrace();
         }

      });
   }

   private String Calculate(String v) {

      if( v.contains("sin")){
         String n = v.substring(0, v.indexOf("sin"));
         String m = v.substring(v.indexOf("sin") + 3, v.length());

         if( n.length() == 0){
            v = String.valueOf(Math.sin(Double.parseDouble(m)));
         }else{
            v = String.valueOf(Math.sin(Double.parseDouble(m)) * Double.parseDouble(n));
         }

      }else if( v.contains("cos")){
         String n = v.substring(0, v.indexOf("cos"));
         String m = v.substring(v.indexOf("cos") + 3, v.length());

         if( n.length() == 0){
            v = String.valueOf(Math.cos(Double.parseDouble(m)));
         }else{
            v = String.valueOf(Math.cos(Double.parseDouble(m)) * Double.parseDouble(n));
         }

      }else if( v.contains("tan")){
         String n = v.substring(0, v.indexOf("tan"));
         String m = v.substring(v.indexOf("tan") + 3, v.length());

         if( n.length() == 0){
            v = String.valueOf(Math.tan(Double.parseDouble(m)));
         }else{
            v = String.valueOf(Math.tan(Double.parseDouble(m)) * Double.parseDouble(n));
         }
      }else if( v.contains("e^")){
         String n = v.substring(0, v.indexOf("e^"));
         String m = v.substring(v.indexOf("e^") + 2, v.length());

         if( n.length() == 0){
            v = String.valueOf(Math.exp(Double.parseDouble(m)));
         }else{
            v = String.valueOf(Math.pow( 2.71828 * Double.parseDouble(n), Double.parseDouble(m)));
         }

      }else if( v.contains("^")){

         String n = v.substring(0, v.indexOf("^"));
         String m = v.substring(v.indexOf("^") + 1, v.length());
         v = String.valueOf(Math.pow(Double.parseDouble(n), Double.parseDouble(m)));

      }else if( v.contains("√")){
         String n = v.substring(0, v.indexOf("√"));
         String m = v.substring(v.indexOf("√") + 1, v.length());

         if( n.length() == 0){
            v = String.valueOf(Math.sqrt(Double.parseDouble(m)));
         }else{
            v = String.valueOf(Math.sqrt(Double.parseDouble(m)) * Double.parseDouble(n));
         }
      }

      return v;
   }



   public static void main(String[] args) {
      launch(args);  
   }

}

2. 결과

공학용계산기