java 简易计算器
程序的实现效果截图
不多说直接上代码
package JavaGuI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class CalculatorJFrame extends JFrame implements ActionListener {
// 定义文本框
JTextField jTextField =new JTextField();
// 定义以下所需要的按钮租组件
JButton jButton0 =new JButton("0");
JButton jButton1 =new JButton("1");
JButton jButton2 =new JButton("2");
JButton jButton3 =new JButton("3");
JButton jButton4 =new JButton("4");
JButton jButton5 =new JButton("5");
JButton jButton6 =new JButton("6");
JButton jButton7 =new JButton("7");
JButton jButton8 =new JButton("8");
JButton jButton9 =new JButton("9");
JButton jButtonPoint =new JButton(".");
JButton jButtonAdd =new JButton("+");
JButton jButtonSub =new JButton("-");
JButton jButtonDiv =new JButton("/");
JButton jButtonMul =new JButton("*");
JButton jButtonEqu =new JButton("=");
JButton jButtonCE =new JButton("CE");
JButton []jButtons ={jButton7,jButton8,jButton9,jButtonDiv,jButtonCE,
jButton4,jButton5,jButton6,jButtonMul,jButtonEqu,
jButton1,jButton2,jButton3,jButtonSub,
jButton0,jButtonPoint,jButtonAdd};
private String StringResult="";
private String stringTemp="0";
public CalculatorJFrame()
{
// 初始化界面
InitJFrame();
// 初始化按钮
InitJButton();
// 页面设置可见
this.setVisible(true);
}
// 初始化界面
public void InitJFrame()
{
// 设置页面尺寸
this.setSize(340,355);
// 设置标题
this.setTitle("计算器
");
// 设置关闭页面时关闭界面
this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// 设置界面置顶
this.setAlwaysOnTop(true);
// 设置界面居中
this.setLocationRelativeTo(null);
this.setLayout(null);
}
// 初始化按钮
public void InitJButton()
{
// 设置文本框的位置与大小
jTextField.setBounds(0,0,340,50);
// 设置文本框不可编辑
jTextField.setEditable(false);
jTextField.setText(stringTemp);
// 设置文本框中的颜色
jTextField.setForeground(Color.BLACK);
jTextField.setFont(new Font("宋体",Font.BOLD,20));
// 将文本框添加到容器中
this.getContentPane().add(jTextField);
// 将按钮添加到容器中
for(int i=0;i<17;i++)
{
if(i<5)
jButtons[i].setBounds(65*i,60,60,60);
else if(i<9) {
jButtons[i].setBounds(65 * (i - 5), 125, 60, 60);
}
else if(i<14)
{ if(i==9)
jButtons[i].setBounds(65 * (i - 5), 125, 60, 190);
else
jButtons[i].setBounds(65 * (i - 10), 190, 60, 60);
}
else {
if(i==14)
jButtons[i].setBounds(0,255,125,60);
else
jButtons[i].setBounds(65*(i-13),255,60,60);
}
// 按钮去焦点
jButtons[i].setFocusPainted(false);
// 给按钮添加动作监听事件
jButtons[i].addActionListener(this);
this.getContentPane().add(jButtons[i]);
}
}
@Override
public void actionPerformed(ActionEvent e) {
JButton obj = (JButton) e.getSource();
// 判断是点击那个按钮
// 如果是点击等于按钮 输出计算结果
if(obj ==jButtonEqu){
jTextField.setText("结果是:"+cal(StringResult));
StringResult ="";
}
// 如果是点击清空按钮 将清空
else if(obj ==jButtonCE){
StringResult ="";
jTextField.setText(stringTemp);
}
// 如果是点击其他的按钮,将按钮的值添加到字符串,用于后续计算
else{
StringResult+=obj.getText();
jTextField.setText(StringResult);
}
}
//计算
public static BigDecimal cal(String str) {
// 对表达式进行预处理,并简单验证是否是正确的表达式
// 存放处理后的表达式
java.util.List<String> list = new ArrayList<>();
char[] arr = str.toCharArray();
// 存放数字临时变量
StringBuilder tmpStr = new StringBuilder();
for (char c : arr) {
// 如果是数字或小数点,添加到临时变量中
if (c >= '0' && c <= '9') {
tmpStr.append(c);
} else if (c == '.') {
if (tmpStr.indexOf(".") > 0) {
throw new RuntimeException("非法字符");
}
tmpStr.append(c);
}
// 如果是加减乘除或者括号,将数字临时变量和运算符依次放入list中
else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')') {
if (tmpStr.length() > 0) {
list.add(tmpStr.toString());
tmpStr.setLength(0);
}
list.add(c + "");
}
// 如果是空格,跳过
else if (c == ' ') {}
else {
throw new RuntimeException("非法字符");
}
}
if (tmpStr.length() > 0) {
list.add(tmpStr.toString());
}
// 初始化后缀表达式
List<String> strList = new ArrayList<>();
// 运算过程中,使用了两次栈结构,第一次是将中缀表达式转换为后缀表达式,第二次是计算后缀表达式的值
Stack<String> stack = new Stack<>();
// 声明临时变量,存放出栈元素
String tmp;
// 1. 将中缀表达式转换为后缀表达式
for (String s : list) {
// 如果是左括号直接入栈
switch (s) {
case "(":
stack.push(s);
break;
// 如果是右括号,执行出栈操作,依次添加到后缀表达式中,直到出栈元素为左括号,左括号和右括号都不添加到后缀表达式中
case ")":
while (!(tmp = stack.pop()).equals("(")) {
strList.add(tmp);
}
break;
// 如果是加减乘除,弹出所有优先级大于或者等于该运算符的栈顶元素(栈中肯定没有右括号,认为左括号的优先级最低),然后将该运算符入栈
case "*":
case "/":
while (!stack.isEmpty()) {
// 取出栈顶元素
tmp = stack.peek();
if (tmp.equals("*") || tmp.equals("/")) {
stack.pop();
strList.add(tmp);
} else {
break;
}
}
stack.push(s);
break;
case "+":
case "-":
while (!stack.isEmpty()) {
// 取出栈顶元素
tmp = stack.peek();
if (!tmp.equals("(")) {
stack.pop();
strList.add(tmp);
} else {
break;
}
}
stack.push(s);
break;
// 如果是数字,直接添加到后缀表达式中
default:
strList.add(s);
break;
}
}
// 最后依次出栈,放入后缀表达式中
while (!stack.isEmpty()) {
strList.add(stack.pop());
}
// 2.计算后缀表达式的值
Stack<BigDecimal> newStack = new Stack<>();
for (String s : strList) {
// 若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,
// 运算后的结果再进栈,直到后缀表达式遍历完毕
if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {
BigDecimal b1 = newStack.pop();
BigDecimal b2 = newStack.pop();
switch (s) {
case "+" -> newStack.push(b2.add(b1));
case "-" -> newStack.push(b2.subtract(b1));
case "*" -> newStack.push(b2.multiply(b1));
case "/" -> newStack.push(b2.divide(b1, 9, BigDecimal.ROUND_HALF_UP));
}
}
// 如果是数字,入栈
else {
newStack.push(new BigDecimal(s));
}
}
// 最后,栈中仅有一个元素,就是计算结果
return newStack.peek();
}
public static void main(String[] args) {
new CalculatorJFrame();
}
}