程式能實現基本的算術運算,並能夠對運算結果的精度進行有效控制,並且實現了儲存空間相關功能
功能如下:
MC:清除儲存資料MR:讀取儲存資料顯示在螢幕上MS:將顯示的資料覆蓋儲存到儲存空間中M+:用儲存的資料加上螢幕上顯示的數並更新儲存空間裡的值M-: 用儲存的資料減去螢幕上顯示的數並更新儲存空間裡的值←: 刪除輸入數的尾數C: 清除計算機資料,下一次輸入資料開始新的運算CE: 清除當前輸入的數±: 正負數轉換√: 開平方+,-,*,/ 加減乘除,將結果%:模數1/x:取倒數
程式流程圖:
代碼實現:
class operateNum {//運算元類public double value;//運算元的實際值public int dotWei;//運算元如果是小數,記錄小數點後的位元public String invertedString;//1/x字串public String sqrtedString;//sqrt(x)字串public boolean isSqrted,isInverted;//做標記是否√,1/x過,用於後續判斷public boolean clear;//clear為真表示是否重設運算元public boolean isFloat;//isFloat為真,表示運算元是小數public operateNum(){value=0;dotWei=0;sqrtedString=null;invertedString=null;isSqrted=false;isInverted=false;clear=false;isFloat=false;}public void reset()//重設運算元{value=0;dotWei=0;sqrtedString=null;invertedString=null;isSqrted=false;isInverted=false;clear=false;isFloat=false;}}
class storageField {//儲存區public double storageNum;//儲存區儲存的資料public boolean storageMode;//是否啟動儲存區public storageField(){storageNum=0;storageMode=false;}}
import java.awt.*;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.math.BigDecimal;import javax.swing.*;import javax.swing.border.Border;import javax.swing.border.LineBorder;public class calc extends JFrame{private JTextField display1,display2,display3;private JButton num[],operate[];private String name[]={"MC","MR","MS","M+","M-","←","CE","C","±","√","7","8","9","/","%","4","5","6","*","1/x","1","2","3","-","=","0",".","+"};private operateNum op1=new operateNum(),op2=new operateNum();//運算元1,運算元2private storageField storage=new storageField();//儲存區private String action="op1";//表示要操作的對象 "op1"操作第一個運算元,"op2"操作第二個運算元private String sign="";//運算子,預設為空白private String screen1,screen2;private boolean Disable=false;public calc(){super("計算機");this.setLayout(null);this.setSize(228, 324);this.setResizable(false);JPanel jp=new JPanel(null);jp.setBounds(10,15,getWidth()-24,getHeight());jp.setBackground(new Color(217,228,241));this.getContentPane().setBackground(new Color(217,228,241));/**顯示屏**/display1=new JTextField("");display2=new JTextField("0");display3=new JTextField("");display1.setEnabled(false);display2.setEnabled(false);display3.setEnabled(false);display1.setBounds(0, 0, 204, 26);display2.setBounds(20, 20, 184, 34);display3.setBounds(0, 20, 20, 34);display1.setHorizontalAlignment(JLabel.RIGHT);display2.setHorizontalAlignment(JLabel.RIGHT);display3.setHorizontalAlignment(JLabel.CENTER);display1.setFont(new Font("宋體",Font.PLAIN,12));display2.setFont(new Font("宋體",Font.BOLD,20));display3.setFont(new Font("宋體",Font.PLAIN,20));display1.setDisabledTextColor(Color.BLACK);display2.setDisabledTextColor(Color.BLACK);display3.setDisabledTextColor(Color.BLACK);display1.setBorder(new LineBorder(new Color(242,247,252)));display2.setBorder(new LineBorder(new Color(242,247,252)));display3.setBorder(new LineBorder(new Color(242,247,252)));display1.setBackground(new Color(242,247,252));display2.setBackground(new Color(242,247,252));display3.setBackground(new Color(242,247,252));/**按鈕 35px*29px 28個***/int i;operate=new JButton[28];/**前24個**/for(i=0;i<24;i++){operate[i]=new JButton(name[i]);operate[i].setMargin(new java.awt.Insets(0,0,0,0)); operate[i].setBounds(i%5*(35+7), 60+i/5*(29+5)+5, 35, 29);jp.add(operate[i]);}/***=號***/operate[i]=new JButton(name[i]);operate[i].setMargin(new java.awt.Insets(0,0,0,0)); operate[i].setBounds(i%5*(35+7), 60+i/5*(29+5)+5, 35, 29*2+5);jp.add(operate[i]);i++;/***0號***/operate[i]=new JButton(name[i]);operate[i].setMargin(new java.awt.Insets(0,0,0,0)); operate[i].setBounds(i%5*(35+7), 60+i/5*(29+5)+5, 35*2+7, 29);jp.add(operate[i]);/**前24個**/for(i=i+1;i<name.length;i++){operate[i]=new JButton(name[i]);operate[i].setMargin(new java.awt.Insets(0,0,0,0)); operate[i].setBounds((i+1)%5*(35+7), 60+i/5*(29+5)+5, 35, 29);jp.add(operate[i]);}/** * 給按鈕註冊滑鼠監聽器,鍵盤監聽器和背景 */mouseAdapter ml=new mouseAdapter();keyAdapter kl=new keyAdapter();for(i=0;i<name.length;i++){operate[i].addMouseListener(ml);operate[i].addKeyListener(kl);operate[i].setBackground(new Color(233,240,247));operate[i].setForeground(new Color(30,57,91));}jp.add(display1);jp.add(display2);jp.add(display3);jp.addKeyListener(kl);this.add(jp);this.setVisible(true);}class mouseAdapter extends MouseAdapter{public void mouseClicked(MouseEvent e){JButton operate=(JButton)e.getSource();if(Disable)//禁用按鈕,點擊C 恢複計算機{if(operate.getText()=="C"){clear();Disable=false;}elsereturn;}switch(operate.getText()){case "MC":mc();break;case "MR":mr();break;case "MS":ms();break;case "M+":mAdd();break;case "M-":mCut();break;case "←":cutEnd();break;case "CE":cutNum();break;case "C":clear();break;case "±":revolt();break;case "√":sqrt();break;case "7":case "8":case "9":case "4":case "5":case "6":case "3":case "2":case "1":case "0":read(Integer.parseInt(operate.getText()));break;//將按鍵上的文本轉化為Int型case "/":divide();break;case "%":mo();break;case "*":mul();break;case "1/x":inverted();break;case "-":cut();break;case "+":add();break;case "=":sum();break;case ".":dot();break;}}public void mouseEntered(MouseEvent e){((JButton)e.getSource()).setBackground(new Color(255,211,113));}public void mouseExited(MouseEvent e){((JButton)e.getSource()).setBackground(new Color(233,240,247));}}/* * MC 取消儲存區,清空儲存區資料 */public void mc(){storage.storageNum=0;storage.storageMode=false;display3.setText(null);}/* * MR 讀取儲存空間儲存的資料 */public void mr(){op1.value=storage.storageNum;screen2=""+op1.value;if(op1.value==Math.floor(op1.value))screen2=""+(int)op1.value;display2.setText(screen2);op1.clear=true;}/* * MS 儲存資料到儲存空間 */public void ms(){storage.storageNum=op1.value;display3.setText("M");//螢幕左下角顯示M標誌}/* * M+ 已經儲存的數加上當前計算結果並將和存入儲存空間 */public void mAdd(){storage.storageNum=storage.storageNum+op1.value;}/* * M- 已經儲存的數減去當前計算結果並將差存入儲存空間 */public void mCut(){storage.storageNum=storage.storageNum-op1.value;}/* * ← 輸入的數去掉尾數 * */public void cutEnd(){if(action=="op1"&&op1.value!=0)//表示對op1進行操作{if(op1.isFloat==false)//如果op1為整數{op1.value=(int)op1.value/10;screen2=""+(int)op1.value;}else{//如果op1為小數BigDecimal bd=new BigDecimal(op1.value); op1.value=bd.setScale(--op1.dotWei,BigDecimal.ROUND_DOWN).doubleValue();screen2=""+op1.value;if(op1.dotWei==0)//小數點後數位都去除掉後,變位整數,更新isFloat標記op1.isFloat=false;}}else if(action=="op2"&&op2.value!=0)//表示對op2進行操作{if(op2.isFloat==false)//如果op2位整數{op2.value=(int)op2.value/10;screen2=""+(int)op2.value;}else{//如果op2為小數BigDecimal bd=new BigDecimal(op2.value); op2.value=bd.setScale(--op2.dotWei,BigDecimal.ROUND_DOWN ).doubleValue();screen2=""+op2.value;if(op2.dotWei==0)//小數點後數位都去除掉後,變位整數,更新isFloat標記op2.isFloat=false;}}display2.setText(screen2);//輸出修改後的運算元}/* * CE 清空當前運算元運算元 */public void cutNum(){if(action=="op1")op1.reset();else if(action=="op2")op2.reset();display2.setText("0");//初始化顯示屏2}/* * C 歸零 重設計算機 */public void clear(){op1.reset();op2.reset();//初始化資料成員action="op1";sign="";//初始化顯示屏display1.setText("");display2.setText("0");}/* * ± 加號或減號 */public void revolt(){if(action=="op1"){op1.value=-op1.value;screen2=""+op1.value;}else if(action=="op2"){op2.value=-op2.value;screen2=""+op2.value;}display2.setText(screen2);}/* * √ 根號 */public void sqrt(){double x;//臨時變數if(action=="op1"){op1.sqrtedString="sqrt("+op1.value+")";op1.value=Math.sqrt(op1.value);op1.isSqrted=true;x=op1.value;}else{op2.sqrtedString="sqrt("+op2.value+")";op2.value=Math.sqrt(op2.value);op2.isSqrted=true;x=op2.value;}screen2=x+"";if(x==Math.floor(x))//如果x為整數{screen2=(int)x+"";//則將浮點數x先轉化為int再轉化成字串}display2.setText(screen2);}/* * 按下數字鍵 */public void read(int value){display2.setFont(new Font("宋體",Font.BOLD,20));//預設字型大小display2.setText(null);//清屏if(op1.clear==true)op1.reset();if(op2.clear==true)op2.reset();if(action=="op1")//表示輸資料給op1{if(op1.isFloat==true)//若op1為浮點數{int i=1;double num=value;++op1.dotWei;while(i<=op1.dotWei){num*=0.1;i++;}op1.value=op1.value+num;//將新的小數點位添加到運算元op1中//因為雙精確度浮點數 其精度比較高,而我們只需取它的op1.dotWei儲存op1.value=Double.parseDouble(String.format("%."+op1.dotWei+"f",op1.value));//因為雙精確度浮點數 其精度比較高,而我們只需取它的op1.dotWei顯示在螢幕上display2.setText(String.format("%."+op1.dotWei+"f", op1.value));}else//op1為整數{op1.value=op1.value*10+value;//將新的整數位加倒op1中display2.setText((int)op1.value+"");//螢幕輸出op1的值}}else if(action=="op2")//表示輸資料給op2{if(op2.isFloat==true)//若op2為浮點數{int i=1;double num=value;++op2.dotWei;while(i<=op2.dotWei){num*=0.1;i++;}op2.value=op2.value+num;//將新的小數點位添加到運算元op2中//因為雙精確度浮點數 其精度比較高,而我們只需取它的op2.dotWei儲存op2.value=Double.parseDouble(String.format("%."+op2.dotWei+"f",op2.value));//因為雙精確度浮點數 其精度比較高,而我們只需取它的op2.dotWei顯示在螢幕上display2.setText(String.format("%."+op2.dotWei+"f", op2.value));}else//op2為整數{op2.value=op2.value*10+value;display2.setText((int)op2.value+"");}}}public void divide(){run("/");}public void mo(){run("%");}public void mul(){run("*");}/* * 1/x */public void inverted(){double num;String str;if(action=="op1"){op1.invertedString="1/"+op1.value;//1/x形式字串op1.value=1/op1.value;op1.isInverted=true;num=op1.value;}else{op2.invertedString="1/"+op2.value;//1/x形式字串op2.value=1/op2.value;op1.isInverted=true;num=op2.value;}str=num+"";if(str.length()>=16)//計算機螢幕所能顯示資料的最大長度{display2.setFont(new Font("宋體",Font.BOLD,14));//縮小字型輸出display2.setText(str.substring(0, 16));}elsedisplay2.setText(str);}public void cut(){run("-");}public void add(){run("+");}public void sum(){display2.setFont(new Font("宋體",Font.BOLD,20));int d1=op1.dotWei,d2=op2.dotWei,i;switch(sign){ //運算後 結果儲存到op1中case "+":op1.value=op1.value+op2.value;break;case "-":op1.value=op1.value-op2.value;break;case "*":op1.value=op1.value*op2.value;break;case "/":op1.value=op1.value/op2.value;break;case "%":op1.value=op1.value%op2.value;break;}if(op2.value==0&&sign=="/")//除數為0{Disable=true;display2.setText(op1.value+"");display1.setText(null);action="op1";return ;}if(op1.value==Math.floor(op1.value))//結果為整數{display2.setText((int)op1.value+"");op1.dotWei=0;op1.isFloat=false;}else{//結果為小數String str=op1.value+"";//準確控制算術運算結果的精度,加,減,模數運算,小數點後的有效數字最多為max(d1,d2)位if(sign.equals("+")||sign.equals("-")||sign.equals("%")){i=d1>d2?d1:d2;str=op1.value+"";str=str.substring(0, str.indexOf(".")+i+1);//取i位輸出}//準確控制算術運算結果的精度,乘法運算,小數點後的有效數字最多為d1+d2位else if(sign.equals("*")){i=d1+d2;BigDecimal bd=new BigDecimal(op1.value); op1.value=bd.setScale(i,BigDecimal.ROUND_DOWN ).doubleValue();str=op1.value+"";//更新修改後的str}//結果超過顯示資料的最大長度if(str.length()>=16){display2.setFont(new Font("宋體",Font.BOLD,14));str=str.substring(0, 16);}display2.setText(str);op1.dotWei=str.length()-str.indexOf(".")-1;//更新op1w值}display1.setText(null);action="op1";op1.clear=true;//開始新的運算式運算時,op1要先重設op2.clear=true;//開始新的運算式運算時,op2要先重設sign="";}public void dot(){if(action=="op1")op1.isFloat=true;elseop2.isFloat=true;display2.setText(display2.getText()+".");}public void run(String SIGN){display2.setFont(new Font("宋體",Font.BOLD,20));action="op2";int d1=op1.dotWei,d2=op2.dotWei,i;if(!sign.equals(""))//檢測是否為以為運算式的第一運算{switch(sign){//運算後 結果儲存到op1中case "+":op1.value=op1.value+op2.value;break;case "-":op1.value=op1.value-op2.value;break;case "*":op1.value=op1.value*op2.value;break;case "/":op1.value=op1.value/op2.value;break;case "%":op1.value=op1.value%op2.value;break;}}String temp=isSpecileHandle();if(temp==null)temp=display2.getText();//先儲存display2文字框裡的資料if(op2.value==0&&sign=="/")//除數為0{Disable=true;display2.setText(op1.value+"");display1.setText(display1.getText()+op1.value);}if(op1.value==Math.floor(op1.value))//結果為整數{display2.setText((int)op1.value+"");op1.dotWei=0;op1.isFloat=false;}else{String str=op1.value+"";//準確控制算術運算結果的精度,加,減,模數運算,小數點後的有效數字最多為max(d1,d2)位if(sign.equals("+")||sign.equals("-")||sign.equals("%")){i=d1>d2?d1:d2;BigDecimal bd=new BigDecimal(op1.value); op1.value=bd.setScale(i,BigDecimal.ROUND_DOWN ).doubleValue();str=op1.value+"";//更新修改後的str}//準確控制算術運算結果的精度,乘法運算,小數點後的有效數字最多為d1+d2位else if(sign.equals("*")){i=d1+d2;BigDecimal bd=new BigDecimal(op1.value); op1.value=bd.setScale(i,BigDecimal.ROUND_DOWN ).doubleValue();str=op1.value+"";//更新修改後的str}//結果超過顯示資料的最大長度if(str.length()>=16){display2.setFont(new Font("宋體",Font.BOLD,14));str=str.substring(0, 16);}display2.setText(str);op1.dotWei=str.length()-str.indexOf(".")-1;//每次加完後,如果結果op1的值為小數則更新op1w的值}sign=SIGN;display1.setText(display1.getText()+temp+sign);op2.value=op1.value;//運算後,運算元op2預設的值為op1的值op2.clear=true;//下一次鍵入資料,op2要重設op1.clear=false;//下一次鍵入資料,op1不要重設}/* * isSpecileHandle() * 運算元是否sqrt()或1/x過, * 如果有,則返回"sqrt(x)"或"1/x"字串 */public String isSpecileHandle(){String temp=null;if(op1.isSqrted){temp=op1.sqrtedString;op1.isSqrted=false;}else if(op2.isSqrted){temp=op2.sqrtedString;op2.isSqrted=false;}if(op1.isInverted){temp=op1.invertedString;op1.isInverted=false;}else if(op2.isInverted){temp=op2.invertedString;op2.isInverted=false;}return temp;}class keyAdapter extends KeyAdapter{public void keyPressed(KeyEvent e){int keycode=e.getKeyCode();if((keycode>=96&&keycode<=105)||(keycode>=48&&keycode<=57))//數字鍵{if(keycode>=96)keycode-=48;switch(keycode){case 48:read(0);break;case 49:read(1);break;case 50:read(2);break;case 51:read(3);break;case 52:read(4);break;case 53:read(5);break;case 54:read(6);break;case 55:read(7);break;case 56:read(8);break;case 57:read(9);break;}}//運算子鍵+ - * / =和. 以及退格鍵(* =號)else if((keycode==110||keycode==46)||(keycode==111||keycode==47)||(keycode==45||keycode==109)||keycode==107||keycode==106||keycode==61||keycode==10||keycode==8){if((keycode==110||keycode==46))dot();else if(keycode==111||keycode==47)run("/");else if(keycode==45||keycode==109)run("-");else if(keycode==107)run("+");else if(keycode==106)run("*");else if(keycode==61||keycode==10)//=號sum();else if(keycode==8)cutEnd();}}}public static void main(String[] args) {// TODO Auto-generated method stubcalc app=new calc();}}
程式截圖