我的计算器. 用java实现的

//我的计算器. 用java实现的 package cross.pauliuyou.calculator.base; import java.math.BigDecimal; import java.math.BigInteger; import java.math.MathContext; import java.util.Vector; /** * * @author 刘优 * @version 1.1 * * * * */ public class CalculateUnit { Vector numbers; Vector operators; public CalculateUnit(Vector nums,Vector ops) { numbers = nums; operators = ops; int j = 0; for (int i = 0; i < operators.size(); i++) { if (getOpObjNum(operators.get(i)) == 1) { numbers.add(i+j,numbers.get(i+j)); j++; } } } public BigDecimal calculate() throws CalculateException { int [] levels = new int[operators.size()]; for (int i = 0; i < levels.length; i++) { levels[i] = i; } sort(levels,operators); for (int i = 0; i < levels.length; i++) { int opPos = levels[i]; char op = operators.get(opPos); int numPos = opPos; int nullPos = -1; int nullNum = 0; boolean move = true; for (int j = opPos; j >=0; j--) { char tm = operators.get(j); if (tm != '0') { move = false; } else { if (!move) { nullPos = j; } nullNum++; } } if (nullPos != -1 && move) { numPos = nullPos; } else { numPos -= nullNum; } int objnum = this.getOpObjNum(op); switch (objnum) { case 1: case 2: BigDecimal left = numbers.get(numPos); BigDecimal right = numbers.get(numPos + 1); BigDecimal rs = cal(left,right,op); numbers.remove(numPos + 1); numbers.remove(numPos); numbers.add(numPos,rs); operators.remove(opPos); operators.add(opPos,'0'); break; case 3: default: break; } } return numbers.get(0); } protected static BigDecimal jie(BigDecimal x) throws CalculateException { if (x.compareTo(BigDecimal.ZERO) == -1 || x.toString().indexOf(".") != -1) { throw new CalculateException("负数或小数不允许算阶乘"); } BigInteger result = BigInteger.ONE; BigInteger num = new BigInteger(x.intValue() + ""); while (num.compareTo(BigInteger.ONE) == 1) { result = result.multiply(num); num = num.subtract(BigInteger.ONE); } return new BigDecimal(result); } private static BigDecimal sqrt(BigDecimal x) throws CalculateException { if (x.compareTo(BigDecimal.ZERO) == -1) { throw new CalculateException("负数不能开平方"); } return new BigDecimal(Math.sqrt(x.doubleValue()) + ""); } public static BigDecimal cal(BigDecimal x,BigDecimal y,char op) throws CalculateException { //System.out.println("cal : " + x + op + y); switch (op) { case '+' : return x.add(y); case '-' : return x.subtract(y); case '*' : return x.multiply(y); case '/' : if (y.compareTo(BigDecimal.ZERO) == 0) { throw new CalculateException("不允许除零!"); } return x.divide(y,MathContext.DECIMAL64); case '!' : return jie(x); case 's' : return sqrt(x); case 'p' : return x.pow(y.intValue()); default : throw new CalculateException("不支持的运算符 :" + op); } } private int getOpObjNum(char c) { if (c == '!' || c == 's') { return 1; } if (c == 'p') { return 2; } if (c == '*' || c == '/') { return 2; } if (c == '+' || c == '-') { return 2; } return 0; } private int getLevel(char c) { if (c == 'p') { return 70; } else if (c == '!' || c == 's') { return 60; } else if (c == '/') { return 50; } else if (c == '*') { return 49; } else if (c == '-') { return 40; } else if (c == '+') { return 39; } return 0; } private void sort(int [] in,Vector ops) { for (int i = 0; i < ops.size(); i++) { int t = getLevel(ops.get(in[i])); int pos = i; for (int j = i + 1; j < ops.size(); j++) { int t2 = getLevel(ops.get(in[j])); if (t2 > t) { t = t2; pos = j; } } if (pos != i) { int ttt = in[i]; in[i] = in[pos]; in[pos] = ttt; } } } public double oldCalculate(Vector numbers,Vector operators) throws CalculateException { BigDecimal d = null; while (operators.size() > 0) { for (int i = 0; i < operators.size(); i++) { char c = operators.get(i); if (getLevel(c) == 0) if (c == '*' || c == '/') { d = cal(numbers.get(i),numbers.get(i + 1),c); numbers.remove(i + 1); numbers.remove(i); numbers.add(i,d); operators.remove(i); break; } boolean hasMutli = false; for (int j = i + 1; j < operators.size(); j++) { if (operators.get(j) == '*' || operators.get(j) == '/') { hasMutli = true; break; } } if (!hasMutli) { d = cal(numbers.get(i),numbers.get(i + 1),operators.get(i)); numbers.remove(i + 1); numbers.remove(i); numbers.add(i,d); operators.remove(i); break; } } } return numbers.get(0).doubleValue(); } public String toString() { return "num : " + numbers.toString() + "/nops : " + operators.toString(); } } package cross.pauliuyou.calculator.base; import java.util.Vector; /** * * @author 刘优 * @version 1.1 * * * * */ public class Queue { private Vector content; public Queue() { content = new Vector (); } public void add(T t) { content.add(t); } public T peek() { if (content.size() == 0) { return null; } return content.get(0); } public T get() { if (content.size() == 0) { return null; } return content.remove(0); } public int size() { return content.size(); } public String toString() { return content.toString(); } } package cross.pauliuyou.calculator.base; import java.util.Vector; /** * * @author 刘优 * @version 1.1 * * * * */ public class Stack { private Vector content; public Stack() { content = new Vector (); } public void push(T t) { content.add(t); } public T peek() { if (content.size() == 0) { return null; } return content.get(content.size() - 1); } public T pop() { if (content.size() == 0) { return null; } return content.remove(content.size() - 1); } public int size() { return content.size(); } public String toString() { return content.toString(); } } package cross.pauliuyou.calculator.base; /** * * @author 刘优 * @version 1.1 * * * * * */ public class CalculateException extends Exception { public CalculateException(String infor) { super(infor); } } package cross.pauliuyou.calculator.main; import cross.pauliuyou.calculator.ui.CalculatorJFrame; public class Main { /** * @param args */ public static void main(String[] args) { new CalculatorJFrame(); } } package cross.pauliuyou.calculator.base; import java.math.BigDecimal; import java.util.Vector; /** * * @author 刘优 * @version 1.1 * * * * */ public class Calculator { private BigDecimal result = BigDecimal.ZERO; private Vector express; private static char[] ops = { '+', '-', '*', '/', '!', 's', 'p' }; private static char[] singleOps = { '-', '!', 's' }; private boolean isSingleOps(char c) { for (int i = 0; i < singleOps.length; i++) { if (c == singleOps[i]) { return true; } } return false; } private void alarm(String infor) throws CalculateException { throw new CalculateException(infor); } private boolean syntax(String str) throws CalculateException { char first = str.charAt(0); if (isOperator(first) && first != '-') { alarm("不能以运算符开头"); return false; } char last = str.charAt(str.length() - 1); if (isOperator(last) && !isSingleOps(last) || last == '.' || last == '-') { alarm("不能以运算符或点号结束"); return false; } int firstQuote = -1; int leftCount = 0; int rightCount = 0; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c == '(') { if (firstQuote == -1) { firstQuote = 1; } leftCount++; if (i > 0) { char leftChar = str.charAt(i - 1); if (leftChar != '(' && !isOperator(leftChar)) { alarm("左括号必须要跟一个运算符 "); return false; } } if (i > str.length() - 5) { alarm("左括号用法错误, (2+3)"); return false; } char rightChar = str.charAt(i + 1); if (rightChar != '(' && !isNumber(rightChar) && rightChar != '-') { alarm("左括号后面要跟一个数 "); return false; } if (rightChar == ')') { alarm("左括号用法错误, (2+3)"); return false; } } if (c == ')') { if (firstQuote == -1) { firstQuote = 2; } rightCount++; if (i < str.length() - 2) { char rightChar = str.charAt(i + 1); if (rightChar != ')' && !isOperator(rightChar)) { alarm("右括号后面要跟一个运算符 "); return false; } } if (i < 4) { alarm("右括号用法错误, (2+3)"); return false; } char leftChar = str.charAt(i - 1); if (leftChar != ')' && !isNumber(leftChar) && !isSingleOps(leftChar)) { alarm("右括号前面必须是一个数 "); return false; } if (leftChar == '(') { alarm("左括号用法错误, (2+3)"); return false; } } if (i < str.length() - 2) { if (isOperator(c) && isOperator(str.charAt(i + 1)) && !isSingleOps(c)) { alarm("运算符不能连续出现"); return false; } } } if (firstQuote == 2) { alarm("左括号必须在前 "); return false; } if (leftCount != rightCount) { alarm("左右括号不匹配 "); return false; } return true; } private void addStrToVector(Vector v,String str) { if (str == null || str.length() == 0) return; for (int i = 0; i < str.length(); i++) { v.add(str.charAt(i)); } } private void addVector(String str) { Stack leftquotes = new Stack (); Queue rightquotes = new Queue (); boolean over = false; boolean found = false; int begin = -1; int end = -1; while (end < str.length() - 1) { over = false; found = false; int oldend = end; for (int i = end + 1; i < str.length(); i++) { char c = str.charAt(i); if (c == '(' && !over) { if (!found) { begin = i; found = true; } leftquotes.push(i); } if (c == ')') { over = true; rightquotes.add(i); if (rightquotes.size() == leftquotes.size()) { end = i; break; } } } if (over) { String strbefore = str.substring(oldend + 1,begin); addStrToVector(express,strbefore); int quotesNum = leftquotes.size(); Vector [] tmp = new Vector[quotesNum]; int before1 = -1; int before2 = -1; Vector before = null; for (int x = 0; x < quotesNum; x++) { tmp[x] = new Vector(); } for (int x = 0; x < quotesNum; x++) { Integer left = leftquotes.pop(); Integer right = rightquotes.get(); if (left != null && right != null) { int now1 = left.intValue(); int now2 = right.intValue(); if (x == 0) { String str3 = str.substring(now1 + 1,now2); addStrToVector(tmp[x],str3); } else { String str1 = str.substring(now1 + 1,before1); String str2 = str.substring(before2 + 1,now2); addStrToVector(tmp[x],str1); tmp[x].add(before); addStrToVector(tmp[x],str2); if (x == quotesNum - 1) { end = now2; } } before1 = now1; before2 = now2; before = tmp[x]; } } express.add(tmp[quotesNum - 1]); } else { for (int i = end + 1; i < str.length(); i++) { char c = str.charAt(i); if (c == '(') { break; } express.add(c); } break; } for (int i = end + 1; i < str.length(); i++) { char c = str.charAt(i); if (c == '(') { end = i - 1; break; } express.add(c); end = i; } } } private BigDecimal calExpress(Vector v) throws CalculateException { Vector nums = new Vector (); Vector operators = new Vector (); String numStr = ""; for (int i = 0; i < v.size(); i++) { Object o = v.get(i); if (i == 0) { if (o.getClass() == Character.class) { if ((Character)o == '-') { numStr += '-'; continue; } } } if (o.getClass() == Vector.class) { nums.add(calExpress((Vector)o)); } else { char c = (Character)o; if (isOperator(c)) { if (numStr.length() > 0) { try { nums.add(new BigDecimal(numStr)); numStr = ""; } catch (Exception e) { throw new CalculateException("数字格式错误"); } } operators.add(c); } else { numStr += c; } } if (i == v.size() - 1) { if (numStr.length() > 0) try { nums.add(new BigDecimal(numStr)); numStr = ""; } catch (Exception e) { throw new CalculateException("数字格式错误"); } } } CalculateUnit unit = new CalculateUnit(nums,operators); return unit.calculate(); } public BigDecimal calculate(String expressStr) throws CalculateException { if (express != null) { express.clear(); } express = new Vector(); if (syntax(expressStr)) { addVector(expressStr); try { result = calExpress(express); return result; } catch (CalculateException e) { alarm(e.getMessage()); } } return BigDecimal.ZERO; } private boolean isNumber(char c) { if (c >= '0' && c <= '9') { return true; } return false; } private boolean isOperator(char c) { for (int x = 0; x < ops.length; x++) { if (c == ops[x]) { return true; } } return false; } } package cross.pauliuyou.calculator.ui; import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.math.BigDecimal; import java.util.Vector; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import cross.pauliuyou.calculator.base.CalculateException; import cross.pauliuyou.calculator.base.Calculator; /** * * @author 刘优 * @version 1.1 * * * */ public class CalculatorJFrame extends JFrame implements ActionListener,KeyListener { private static final long serialVersionUID = 1L; private JTextArea screen; private JTextField screen2; private JButton[] buttons; private JDialog dialog; private Container dialogPane; private Vector express; private static char[] ops = { '+', '-', '*', '/', '!', 's', 'p' }; private static String keyPermited = "0.123456789+-*/=sp/n/r"; private boolean calculated; private BigDecimal result = BigDecimal.ZERO; private Calculator calculator; class MenuActionListener implements ActionListener { public void actionPerformed(ActionEvent ae) { JMenuItem menuItem = (JMenuItem) ae.getSource(); String cmd = menuItem.getActionCommand(); // screen.append(cmd); if (cmd.equals("打开")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("保存")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("另存为")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("退出")) { System.exit(0); } else if (cmd.equals("复制")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("剪切")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("粘贴")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("查看")) { alarm("菜单 : " + cmd, false); } else if (cmd.equals("主题")) { alarm("此计算器可以计算复杂表达式", false); } else if (cmd.equals("关于")) { showAbout(); } } } public CalculatorJFrame() { super("计算器 - 作者:刘优"); screen = new JTextArea(4, 24); screen2 = new JTextField(26); String[] buttonStrings = { "乘方", "整数", "回退", "清空", "阶乘", "(", ")", "开方", "1", "2", "3", "+", "4", "5", "6", "-", "7", "8", "9", "*", ".", "0", "=", "/" }; String[] actionCommand = { "Pow", "Int", "Back", "CE", "!", "(", ")", "Sqrt", "1", "2", "3", "+", "4", "5", "6", "-", "7", "8", "9", "*", ".", "0", "=", "/" }; String[] toolTipString = { "乘方", "把结果转为整数", "删除一个字符", "清空结果重新计算", "阶乘", "左括号", "右括号", "开平方", "", "", "", "加", "", "", "", "减或负数", "", "", "", "乘", "", "", "计算", "除" }; buttons = new JButton[buttonStrings.length]; Font buttonFont = new Font("宋体", Font.PLAIN, 12); for (int i = 0; i < buttons.length; i++) { buttons[i] = new JButton(buttonStrings[i]); buttons[i].setActionCommand(actionCommand[i]); buttons[i].setFont(buttonFont); buttons[i].setToolTipText(toolTipString[i]); } dialog = new JDialog(this, "消息窗口", true); express = new Vector(); calculated = false; myInit(); addEventHandle(); showMe(); } private void myInit() { this.setJMenuBar(getMenu()); screen.setFont(new Font("", Font.BOLD, 15)); screen.setEditable(false); screen.setToolTipText("主屏幕"); screen.setAutoscrolls(true); screen2.setEditable(false); JPanel northPane = new JPanel(); JPanel centerPane = new JPanel(new GridLayout(6, 4, 6, 8)); JScrollPane scroll = new JScrollPane(screen); northPane.add(scroll); for (int i = 0; i < buttons.length; i++) { centerPane.add(buttons[i]); } add(northPane, "North"); add(centerPane); add(new JPanel(), "West"); add(new JPanel(), "East"); JPanel result2Panel = new JPanel(); result2Panel.add(screen2); add(result2Panel, "South"); } private void addEventHandle() { screen.addKeyListener(this); for (int i = 0; i < buttons.length; i++) { buttons[i].addActionListener(this); } } private JMenuBar getMenu() { JMenuBar menuBar = new JMenuBar(); JMenu menuFile = new JMenu("文件 "); JMenu menuEdit = new JMenu("编辑 "); JMenu menuView = new JMenu("查看 "); JMenu menuHelp = new JMenu("帮助 "); menuBar.add(menuFile); menuBar.add(menuEdit); menuBar.add(menuView); menuBar.add(menuHelp); JMenuItem menuItemFileOpen = new JMenuItem("打开"); JMenuItem menuItemFileSave = new JMenuItem("保存"); JMenuItem menuItemFileSaveAs = new JMenuItem("另存为"); JMenuItem menuItemFileExit = new JMenuItem("退出"); JMenuItem menuItemEditCopy = new JMenuItem("复制"); JMenuItem menuItemEditCut = new JMenuItem("剪切"); JMenuItem menuItemEditPaste = new JMenuItem("粘贴"); JMenuItem menuItemViewView = new JMenuItem("查看"); JMenuItem menuItemHelpTopic = new JMenuItem("主题"); JMenuItem menuItemHelpAbout = new JMenuItem("关于"); menuFile.add(menuItemFileOpen); menuFile.add(menuItemFileSave); menuFile.add(menuItemFileSaveAs); menuFile.addSeparator(); menuFile.add(menuItemFileExit); menuEdit.add(menuItemEditCopy); menuEdit.add(menuItemEditCut); menuEdit.addSeparator(); menuEdit.add(menuItemEditPaste); menuView.add(menuItemViewView); menuHelp.add(menuItemHelpTopic); menuHelp.addSeparator(); menuHelp.add(menuItemHelpAbout); MenuActionListener menuListener = new MenuActionListener(); menuItemFileOpen.addActionListener(menuListener); menuItemFileSave.addActionListener(menuListener); menuItemFileSaveAs.addActionListener(menuListener); menuItemFileExit.addActionListener(menuListener); menuItemEditCopy.addActionListener(menuListener); menuItemEditCut.addActionListener(menuListener); menuItemEditPaste.addActionListener(menuListener); menuItemViewView.addActionListener(menuListener); menuItemHelpTopic.addActionListener(menuListener); menuItemHelpAbout.addActionListener(menuListener); return menuBar; } private void showMe() { int width = 310; int height = 370; setSize(width, height); setLocation(350, 150); this.setResizable(false); setVisible(true); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); dialog.setSize(270, 110); dialog.setLocation(this.getX() + 100, this.getY() + 100); dialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); dialog.setResizable(false); dialogPane = dialog.getContentPane(); } private void showAbout() { dialog.setTitle("关于本软件"); dialogPane.removeAll(); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(3, 1)); JTextField f1 = new JTextField("名称 /t: 计算器"); f1.setEditable(false); panel.add(f1); f1 = new JTextField("作者 /t: 刘优"); f1.setEditable(false); panel.add(f1); f1 = new JTextField("日期 /t: 2007-08"); f1.setEditable(false); panel.add(f1); dialogPane.add(panel); dialog.setLocation(this.getX() + 100, this.getY() + 100); dialog.setVisible(true); } private void backSpace() { String str = screen.getText(); if (str.length() > 0) screen.setText(str.substring(0, str.length() - 1)); } public void actionPerformed(ActionEvent e) { screen.requestFocus(); String cmd = e.getActionCommand(); char c = cmd.charAt(0); if (c == 'C') { clear(); } else if (c == 'B') { backSpace(); } else if (c == 'P') { doOperator('p'); } else if (c == 'I') { /* String bigint = result.toString(); int dot = bigint.indexOf("."); if (dot != -1) { String afterdot = "0" + bigint.substring(dot); double d = Double.parseDouble(afterdot); if (d > 0.54) { bigint = result.intValue() + 1 + ""; } else { bigint = bigint.substring(0, dot); } } String str = screen.getText(); int equalPos = str.indexOf("="); if (equalPos != -1) { screen.setText(str.substring(0, equalPos + 2) + bigint); result = new BigDecimal(bigint); } */ String intValue = result.intValue() + ""; screen.setText(intValue); result = new BigDecimal(intValue); } else if (c == 'S') { doOperator('s'); } else if (c == '=') { enter(); } else if (c == '(' || c == ')') { screen.append(cmd); } else if (isOperator(c)) { doOperator(c); } else if (isNumber(c)) { doNumber(c); } else if (cmd.equals(".")) { screen.append("."); } } private void clear() { screen.setText(""); toZero(); calculated = false; } private void doNumber(char c) { if (calculated) { screen.setText(c + ""); calculated = false; } else { screen.append(c + ""); } } private void doOperator(char c) { if (calculated) { screen.setText(result.toString() + c); calculated = false; } else { screen.append(c + ""); } } private void enter() { if (!calculated) { if (calculator == null) { calculator = new Calculator(); } try { String theText = result.toString().trim(); if (screen2.getText().trim().length () + theText.length() + 4 > screen2.getColumns()) { screen2.setText(theText); } else { screen2.setText(screen2.getText() + " " + theText); } result = calculator.calculate(screen.getText()); screen.append("/n=" + result.toString()); } catch (CalculateException e) { alarm(e.getMessage()); } } else { screen.setText(result.toString()); } calculated = true; toZero(); } private void alarm(String infor) { alarm(infor, true); } private void alarm(String infor, boolean serious) { dialogPane.removeAll(); JLabel label = new JLabel("信息", JLabel.CENTER); dialog.setTitle("信息"); if (serious) { dialog.setTitle("错误!!"); label = new JLabel("发生错误 : ", JLabel.CENTER); } JLabel label2 = new JLabel(infor, JLabel.CENTER); label2.setFont(new Font("宋体", Font.BOLD, 16)); label2.setForeground(Color.red); dialogPane.add(label, "North"); dialogPane.add(label2); dialog.setLocation(this.getX() + 100, this.getY() + 100); dialog.setVisible(true); } private void toZero() { express.clear(); } private boolean isKeyPermited(char c) { for (int i = 0; i < keyPermited.length(); i++) { if (c == keyPermited.charAt(i)) { return true; } } return false; } public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if (code == 27) { clear(); } boolean shift = e.isShiftDown(); if (shift && code == 57) { screen.append("("); return; } else if (shift && code == 48) { screen.append(")"); return; } char c = e.getKeyChar(); if (isKeyPermited(c)) { if (c == '=' || c == '/n' || c == 'r') { enter(); } else { if (isOperator(c)) { doOperator(c); } if (isNumber(c)) { doNumber(c); } } } if (code == 8) { backSpace(); } } private boolean isNumber(char c) { if (c >= '0' && c <= '9') { return true; } return false; } private boolean isOperator(char c) { for (int x = 0; x < ops.length; x++) { if (c == ops[x]) { return true; } } return false; } public void keyReleased(KeyEvent e) { } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值