实验项目1 计算器的设计与实现
实验目的
(1)能通过设计的按钮控件实现简单的算术运算,要求表达式能在编辑框中显示,能将运算结果,输出在编辑框内显示;
(2)能够实现混合运算的求解,算数表达式中包括加减乘除括号等运算符;并且能够识别括号,优先级正确。
(3)能保存历史的表达式运算记录。
实验工具
idea,使用java控制台来完成编写。
算法思路
中缀表达式;后缀表达式。
双栈算符优先级法。
(1)当扫描到的是运算数,则将其压入栈OPND,
(2)当扫描到的是运算符时:
如果这个运算符比OP栈顶的优先级高,则入栈;
如果这个运算符比OP栈顶的运算符优先级低,则从OPND栈中弹出两个运算数,从OP栈中弹出栈顶运算符进行运算,并将结果压入栈OPND。
(3)继续处理当前字符,直到遇到结束符为止。
JAVA程序设计
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Calculator extends JFrame{
}
首先新建一个新建一个继承自 JFrame 的 Calculator类,接下来进行窗口的实现。
设置按键及文本框位置,总体布局(例)
//设置窗口
JFrame jf = new JFrame ("计算器");
jf.setLayout(null);
//放置数字0
button0 = new JButton("0");
button0.setBounds(20, 200, 145, 25);
jf.add(button0);
expressText = new JTextField();
expressText.setBounds(20, 10, 300, 30);
jf.add(expressText);
接着,插入监听器
设置运算符符号为红色,便于分辨
buttonadd.setForeground(Color.red);
buttonequal.setForeground(Color.red);
buttonexcept.setForeground(Color.red);
buttonleft.setForeground(Color.red);
buttonright.setForeground(Color.red);
buttonreduce.setForeground(Color.red);
buttonride.setForeground(Color.red);
接着,设置按动各按键后的处理(例)
public void actionPerformed(ActionEvent e) {
//当按钮为0时;e.getSource获取事件源
if(e.getSource().equals(button0)) {
s=numberText.getText();
if(s.length()>8) {
}
else if(s.equals("0") || equalbook == 1) {
}else {
numberText.setText(s + "0");
}
}
中缀表达式转换为逆波兰表达式,考虑符号优先级
String[] ansString = new String[100];
int Size = 0;
//创建一个栈
Stack<Character> Operater = new Stack<Character>();
s = expressText.getText();
char ch[] = s.toCharArray();
int length = ch.length;
for(int j = 0; j < length; j++) {
//当数组元素为数字时
if(ch[j] >='0' && ch[j] <= '9') {
double Number = ch[j] - '0';
//继续往后遍历,直到不是数字和小数点
//记录小数点是否出现
int point = 0;
int bit = 1;
if(j==length-1) {
ansString[Size++] = String.valueOf(Number);
}
for(j++; j<length; j++) {
if((ch[j] < '0' || ch[j] >'9') && ch[j]!='.') {
j--;
ansString[Size++] = String.valueOf(Number);
break;
}
if(ch[j] == '.') {
point = 1;
continue;
}
if(ch[j] >= '0' && ch[j] <= '9') {
/*
* 当小数点没有出现时和没出现时要分开讨论
*/
if(point == 0) {
Number = Number * 10 + (ch[j] - '0');
} else {
Number = Number + Math.pow(10, -bit) * (ch[j]-'0');
bit++;
}
}
}
} else { //考虑运算符
if(ch[j] =='(') {
Operater.push('(');
} else if(ch[j]==')') {
while(!Operater.peek().equals('(')) {
ansString[Size++] = String.valueOf(Operater.peek());
Operater.pop();
}
Operater.pop();
} else {
if(Operater.empty()) {
Operater.push(ch[j]);
}
else {
while(true) {
if(Operater.empty()) {
Operater.push(ch[j]);
break;
}
char operater1 = Operater.peek();
if((ch[j] == '*' || ch[j] == '/') &&
(operater1=='+' || operater1=='-') || (operater1=='(' || operater1 == ')')) {
Operater.push(ch[j]);
break;
}
else {
ansString[Size++] = String.valueOf(Operater.peek());
Operater.pop();
}
}
}
}
}
}
while(!Operater.empty()) {
ansString[Size++] = String.valueOf(Operater.peek());
Operater.pop();
}
//最后计算逆波兰表达式的值
Stack<Double> Last = new Stack<Double>();
for(int i=0; i<Size; i++) {
String s1 = ansString[i];
char ch2[] = s1.toCharArray();
if(ch2[0]>='0' && ch2[0]<='9') {
Last.push(Double.parseDouble(s1));
}
else {
double num1 = Last.pop();
double num2 = Last.pop();
double num3 = 0;
if(ch2[0]=='+')
num3 = num2 + num1;
else if(ch2[0]=='-')
num3 = num2 - num1;
else if(ch2[0]=='*')
num3 = num2 * num1;
else if(ch2[0]=='/')
num3 = num2 / num1;
Last.push(num3);
}
}
expressText.setText(expressText.getText() + "=" + Last.pop());
equalbook = 1;
}
}
}