成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java 實(shí)現(xiàn)簡(jiǎn)單計(jì)算器

thekingisalwaysluc / 3435人閱讀

摘要:對(duì)于理論算法不再這累贅了。在查閱資料的時(shí)候發(fā)現(xiàn)算法不管用棧還是正則等等,似乎只處理操作符是的數(shù),這是很不可取的。所以需要先將中綴表達(dá)式轉(zhuǎn)化成后綴并標(biāo)記多位數(shù)的操作符,然后在處理后綴表達(dá)式。

最后一次更新于2019/07/08

效果演示圖

功能與流程

要制作一個(gè)簡(jiǎn)易計(jì)算器,首先你要清楚GUI里要顯示什么:

結(jié)果顯示框

0~9的數(shù)字

刪除功能

清楚功能

搜尋歷史記錄功能

計(jì)算結(jié)果的功能

括號(hào)優(yōu)先計(jì)算功能

接下來(lái)通過(guò)流程圖簡(jiǎn)單介紹一下思路:

GUI 源碼

以下代碼是根據(jù)我的設(shè)計(jì)來(lái)編寫(xiě)的

/**
 * @author Hephaest
 * @since  2018/04/19
 * JDK 1.6
 */
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
/**
 * Calculator類(lèi)用來(lái)創(chuàng)造GUI
 */
public class Calculator extends JFrame
{
    //新建文本框
    JTextField text = new JTextField();
    // set up row 2
    JPanel row2 = new JPanel();
    //創(chuàng)建按鈕們
    String[][] buttons = {{"7","8","9","DEL","AC"},{"4","5","6","×","÷"},{"1","2","3","+","-"},{"0","(",")","Replay","="}};
    JButton[][]button = new JButton[4][5];
    /**
     * 這個(gè)計(jì)算機(jī)的界面我模擬的是卡西歐fx-82ES PLUS A
     * 但是僅有其中的部分功能
     */
    public Calculator()
    {
        super("CASIO");
        setSize(400,300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
        //設(shè)置文本框的尺寸、位置以及禁止鍵盤(pán)輸入
        text.setPreferredSize(new Dimension(30, 40));
        text.setHorizontalAlignment(SwingConstants.TRAILING);
        text.setEditable(false);
        getContentPane().add(text, BorderLayout.NORTH);
        //聲明每一個(gè)按鈕代表的意義
        add(row2, BorderLayout.CENTER);
        GridLayout layout2 = new GridLayout(4,5,5,5);
        row2.setLayout(layout2);
        for(int i = 0; i < buttons.length; i++)
        {
            for(int j = 0; j < buttons[0].length; j++)
            {
                button[i][j] = new JButton(buttons[i][j]);
                row2.add(button[i][j]);
            }
        }
        add(row2);
        setResizable(false);
        setVisible(true);
    }
    
    private static void setLookAndFeel() 
    {
        //這條使跨操作系統(tǒng)也能看到計(jì)算機(jī)的GUI
        try {
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            // ignore error
        }
    }
    
    public static void main(String[] args) 
    {
        Calculator.setLookAndFeel();
        Calculator cl = new Calculator();
        cl.listener();
    }
    /**
     * 事件監(jiān)聽(tīng)器,一旦按下按鈕就要根據(jù)操作歷史進(jìn)行相應(yīng)的反應(yīng)
     */
    public void listener()
    {
        Listener l = new Listener(this);
        for(int i = 0; i < buttons.length; i++)
        {
            for(int j = 0; j < buttons[0].length; j++)
            {
                button[i][j].addActionListener(l);
            }
        }
    }
}
事件監(jiān)聽(tīng)器源碼

有了按鈕后下一步就是要想辦法實(shí)現(xiàn)按鈕功能,我的思路在上面流程圖里給過(guò)了,不再累贅,直接看如何利用代碼實(shí)現(xiàn):

/**
 * @author Hephaest
 * @since  2018/04/19
 * JDK 1.6
 */
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JTextField;
/**
 * Listener 類(lèi)
 * 用來(lái)將按鈕輸入的結(jié)果通過(guò)鏈表的方式一個(gè)字一個(gè)字存儲(chǔ)在字符串里,然后調(diào)用另一類(lèi)計(jì)算整個(gè)字符串,返回一個(gè)值
 */
public class Listener implements ActionListener
{
    private Calculator cl;
    private ArrayList list=new ArrayList();
    private ArrayList his=new ArrayList();//這個(gè)鏈表用來(lái)添加每一次得到的最終的結(jié)果
    private ArrayList arr = new ArrayList();//把his里的一整串字符分割成單個(gè)字符,再連接
    private String[] arrayStr = new String[] {};//儲(chǔ)存單次的歷史記錄
    private String out = "";
    private String output = "";
    
    public Listener(Calculator cl)
    {
        this.cl = cl;
    }
    
    public void actionPerformed(ActionEvent event)
    {
        JButton button = (JButton) event.getSource();
        /**
         * 如果點(diǎn)“=”,計(jì)算整個(gè)表達(dá)式的結(jié)果,如果是錯(cuò)誤表達(dá)式,在文本框輸入“Input Error!”
         */
        if(button.getText().equals("="))
        {
            try
            {    
                Function f = new Function();
                double result = f.compute(out);
                cl.text.setText(Double.toString(result));
            } catch(Exception e) {
                cl.text.setText("Input Error!");
            }
        } else if(button.getText().equals("×")) {
            /**
             * 如果點(diǎn)擊"×",先把它轉(zhuǎn)換為"*"
             */
            if(list.isEmpty())
            {
                arr.add("*");
                output += "*";
                out = output;
                cl.text.setText(output);
            } else {
                list.add("*");
                output += "*";
                out = output;
                cl.text.setText(output);
            }
        } else if(button.getText().equals("÷")) {
            /**
             * 如果點(diǎn)擊"÷",把它轉(zhuǎn)換為"/"
             */
            if(list.isEmpty())
            {
                arr.add("/");
                output += "/";
                out = output;
                cl.text.setText(output);
            } else {
                list.add("/");
                output += "/";
                out = output;
                cl.text.setText(output);
            }
        } else if(button.getText().equals("DEL")) {
            /**
             * 如果點(diǎn)擊"DEL",刪除表達(dá)式里最后一個(gè)字符,每點(diǎn)一次刪一個(gè)
             */
            if(list.isEmpty())
            {
                arr.remove(arr.size()-1);
                output = "";
                for(int i = 0; i < arr.size(); i++) output += arr.get(i);
                 out = output;
                 cl.text.setText(output);
            } else {
                list.remove(list.size()-1);
                String output = "";
                for(int i = 0; i < list.size(); i++) output+=list.get(i);
                 out = output;
                 cl.text.setText(output);
            }
        } else if(button.getText().equals("AC")) {
            /**
             * 如果點(diǎn)擊"AC",刪除list鏈表,再刪除之前先把表達(dá)式保留到his的鏈表里
             */
            his.add(out);
            list.clear();
            output="";
             cl.text.setText(output);
        } else if(button.getText().equals("Replay")) {
            /**
             * 如果點(diǎn)擊"Replay",在文本框里顯示上一條表達(dá)式
             */
            output=his.get(his.size()-1);
            cl.text.setText(output);
            arr.clear();
            //把上一條表達(dá)式分割成單個(gè)字符的字符數(shù)組
            char[] a=output.toCharArray();
            for(int i=0;i
計(jì)算器表達(dá)式算法

關(guān)于如何分析整個(gè)表達(dá)式并計(jì)算出正確值,實(shí)踐了一下,還是后綴表達(dá)式比較方便,不用考慮括號(hào)這種優(yōu)先級(jí)問(wèn)題。對(duì)于理論算法不再這累贅了。在查閱資料的時(shí)候發(fā)現(xiàn)算法不管用棧還是正則等等,似乎只處理操作符是0~9的數(shù),這是很不可取的。什么意思呢?就是像10/5這樣的算數(shù)是沒(méi)辦法解決的,只能解決像5/5這樣的。所以需要先將中綴表達(dá)式轉(zhuǎn)化成后綴并標(biāo)記多位數(shù)的操作符,然后在處理后綴表達(dá)式。

/**
 * @author Hephaest
 * @since  2018/07/13
 * JDK 1.6
 */
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class function {
    private String[] str=new String[10];
    private int begin;
    public function(){}
    /**
     * 中綴表達(dá)式轉(zhuǎn)換成后綴表達(dá)式
     * @param exp 在計(jì)算器上顯示的文本 中綴表達(dá)式
     * @return 正確的計(jì)算結(jié)果
     */
    public double compute(String exp) 
    {
        char[] ch = exp.toCharArray();
        Stack  stack = new Stack<>();
        String convertToPostfix = new String();
        int size = ch.length;
        begin = 0;
        for (int i = 0; i < size; i++) {
          //遇到左括號(hào)直接入棧
          if(ch[i] == "(") stack.push(ch[i]);
          else if(ch[i] == ")") {
              //遇到右括號(hào)出棧(追加到后綴表達(dá)式), 直到出棧的元素為左括號(hào)或?yàn)?
              char popValue = stack.pop();
              do 
              {
                  convertToPostfix = convertToPostfix.concat(String.valueOf(popValue));
                  popValue = stack.pop();
              }while(!stack.isEmpty() && popValue != "(");
          } else if(checkOperator(ch[i])) {
              /*
               * 遇到運(yùn)算符需要判斷:
               * 1.是否為空棧,是的話(huà)直接入棧
               * 2.即將入棧的運(yùn)算符是否比棧頂元素優(yōu)先級(jí)高
               *     是,直接入棧
               *    否,棧頂元素出棧(追加到后綴表達(dá)式),當(dāng)前運(yùn)算符入棧
               */
              if(stack.isEmpty()) stack.push(ch[i]);
              else {
                  char popValue = stack.pop();
                  while(checkPriority(popValue,ch[i]))
                  {
                      convertToPostfix = convertToPostfix.concat(String.valueOf(popValue));
                      if(stack.isEmpty()) break;
                      popValue = stack.pop();
                  }
                  if(!checkPriority(popValue,ch[i])) stack.push(popValue);
                  stack.push(ch[i]);
              }
          } else if(checkDigital(ch[i])) {
              /*
               * 單個(gè)數(shù)字直接追加到后綴表達(dá)式
               * 含有不止一個(gè)數(shù)字的操作符需要做記錄:
               *     1.計(jì)算該操作符的起始位置和終止位置
               *     2.把數(shù)字傳到字符串?dāng)?shù)組里(全局變量,下一步需要用到)
               */
              if(i + 1 < size && i - 1 >= 0)
              {
                  if(checkDigital(ch[i - 1]) && !checkDigital(ch[i + 1]))
                  {
                      int end = i;
                      int j = end;
                      while(checkDigital(ch[j]))
                      {
                          j--;
                      }
                      j++;
                      List elements = new LinkedList<>();
                      do
                      {
                          elements.add(String.valueOf(ch[j]));
                          j++;
                      } while(j <= end);
                      str[begin] = String.join("", elements);
                      System.out.println(str[begin]);
                      begin++; 
                  }
              }
              convertToPostfix=convertToPostfix.concat(String.valueOf(ch[i]));
            }
         }
        //第一遍結(jié)束后把棧中剩下的操作符依次出棧(追加到后綴表達(dá)式)
        while(!stack.isEmpty())
        {
            char popValue = stack.pop();
            convertToPostfix = convertToPostfix.concat(String.valueOf(popValue));
        }
        System.out.println(convertToPostfix);
        return computeResult(convertToPostfix);
    }
    
    /**
     * 計(jì)算后綴表達(dá)式
     * @param convertToPostfix 后綴表達(dá)式的字符串
     * @return 計(jì)算結(jié)果
     */
    public double computeResult(String convertToPostfix)
    {
        int[] index=new int[10];
        /*
         * 判斷是否有多位數(shù)的操作符,有的話(huà)找到在后綴表達(dá)式的初始位置
         * 如果沒(méi)有的話(huà)就不會(huì)執(zhí)行
         */
        for(int i = 0;i < begin; i++)
        {
            index[i] = convertToPostfix.indexOf(str[i]);
            System.out.println(index[i]);
        }
        char[] ch = convertToPostfix.toCharArray();
        Stack  stack = new Stack<>();
        double result = 0;
        for (int i = 0; i < ch.length; i++) {
            //如果是運(yùn)算符,pop出棧頂?shù)膬蓚€(gè)元素,記住先進(jìn)后出
            if(checkOperator(ch[i]))
            {
                double num2=stack.pop();
                System.out.println("num2" + num2);
                System.out.print("
");
                double num1=stack.pop();
                System.out.println("num1" + num1);
                System.out.print("
");
                switch(ch[i])
                {
                    case "*":
                        result = num2 * num1;
                        break;
                    case "/":
                        result = num1 / num2;
                        break;
                    case "+":
                        result = num1 + num2;
                        break;
                    case "-":
                        result = num1 - num2;
                        break;
                }
                System.out.println(result);
                stack.push(result);
            } else {
            /*
             * 對(duì)于多位操作符,需要把單個(gè)字符連接起來(lái)然后作為一個(gè)雙精度數(shù)放入棧中
             * 一位數(shù)的操作符直接放入棧即可,注意從字符變成數(shù)字時(shí)要減去48(0的字符型數(shù)據(jù))
             */
                int stop = 0;
                for(int j = 0; j < begin; j++)
                {
                    if(i == index[j])
                    {
                        int start=i;
                        List elements = new LinkedList<>();
                        do
                        {
                            elements.add(String.valueOf(ch[i]));
                            i++;
                        } while(i < str[j].length() + start);
                        i--;
                        String test=String.join("", elements);
                        stack.push(Double.valueOf(test));
                        stop=1;
                        break;
                    }
                }
                if(stop == 0) stack.push((double)ch[i]-48);
            }
        }
        System.out.print("
");
        System.out.print(result);
        return result;
    }
    
    /**
     * 判斷是否是運(yùn)算符
     * @param c 當(dāng)前字符
     * @return 布爾型結(jié)果
     */
    public boolean checkOperator(char c)
    {
        int result;
        switch(c)
        {
            case "+":
            case "-":
            case "*":
            case "/":
                result = 1;
                break;
            default:
                result = 0;
        }
        if(result == 1) return true;
        else return false;
    }
    
    /**
     * 判斷是否是數(shù)字
     * @param c 當(dāng)前字符
     * @return 布爾型結(jié)果
     */
    public boolean checkDigital(char c)
    {
        int num = c;
        num -= 48;
        if(num >= 0 && num <= 9) return true;
        else return false;
    }
    
    /**
     * 判斷即將入棧的優(yōu)先級(jí)是否更高
     * @param popOne 棧頂元素
     * @param checkOne 即將入棧元素
     * @return 布爾型結(jié)果
     */
    public boolean checkPriority(char popOne,char checkOne)
    {
        if((popOne == "*" || popOne == "/") && (checkOne == "+" || checkOne == "-")) return true;
        else if(popOne == checkOne) return true;
        else return false;
    }
}
源碼地址

如果我的文章可以幫到您,勞煩您點(diǎn)進(jìn)源碼點(diǎn)個(gè) ★ Star 哦!
https://github.com/Hephaest/S...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69137.html

相關(guān)文章

  • 《十萬(wàn)字Java入門(mén)練習(xí)100例》1-10例——紙上得來(lái)終覺(jué)淺,絕知此事要躬行

    摘要:代碼實(shí)現(xiàn)在控制臺(tái)打印總結(jié)本篇文章帶大家搭好環(huán)境,并體驗(yàn)了控制臺(tái)打印。輸出結(jié)果總結(jié)熟練掌握取余和整除運(yùn)算,大有作用。終止本次循環(huán),繼續(xù)執(zhí)行下一次循環(huán)。 ?本文收錄...

    keithyau 評(píng)論0 收藏0
  • 來(lái),了解一下Java內(nèi)存模型(JMM)

    摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線(xiàn)程場(chǎng)景下會(huì)存在緩存一致性問(wèn)題。有沒(méi)有發(fā)現(xiàn),緩存一致性問(wèn)題其實(shí)就是可見(jiàn)性問(wèn)題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書(shū)中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說(shuō)自己更懵了。本文,就來(lái)整體的...

    kviccn 評(píng)論0 收藏0
  • 來(lái),了解一下Java內(nèi)存模型(JMM)

    摘要:因?yàn)楣芾砣藛T是了解手下的人員以及自己負(fù)責(zé)的事情的。處理器優(yōu)化和指令重排上面提到在在和主存之間增加緩存,在多線(xiàn)程場(chǎng)景下會(huì)存在緩存一致性問(wèn)題。有沒(méi)有發(fā)現(xiàn),緩存一致性問(wèn)題其實(shí)就是可見(jiàn)性問(wèn)題。 網(wǎng)上有很多關(guān)于Java內(nèi)存模型的文章,在《深入理解Java虛擬機(jī)》和《Java并發(fā)編程的藝術(shù)》等書(shū)中也都有關(guān)于這個(gè)知識(shí)點(diǎn)的介紹。但是,很多人讀完之后還是搞不清楚,甚至有的人說(shuō)自己更懵了。本文,就來(lái)整體的...

    eccozhou 評(píng)論0 收藏0
  • [Java并發(fā)-7]java的線(xiàn)程小節(jié)

    摘要:在領(lǐng)域,實(shí)現(xiàn)并發(fā)程序的主要手段就是多線(xiàn)程??蛇\(yùn)行狀態(tài)指的是線(xiàn)程可以分配執(zhí)行。當(dāng)?shù)却氖录霈F(xiàn)了,線(xiàn)程就會(huì)從休眠狀態(tài)轉(zhuǎn)換到可運(yùn)行狀態(tài)。導(dǎo)出線(xiàn)程棧,分析線(xiàn)程狀態(tài)是診斷并發(fā)問(wèn)題的一個(gè)重要工具。 在 Java 領(lǐng)域,實(shí)現(xiàn)并發(fā)程序的主要手段就是多線(xiàn)程。線(xiàn)程是操作系統(tǒng)里的一個(gè)概念,雖然各種不同的開(kāi)發(fā)語(yǔ)言如 Java、C# 等都對(duì)其進(jìn)行了封裝,但原理和思路都是相同都。Java 語(yǔ)言里的線(xiàn)程本質(zhì)上就是...

    Sunxb 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<