用Java实现一个拥有极简计算计算的计算器
界面展示
项目地址
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 40 |
Estimate | 估计这个任务需要多少时间 | 15 | 10 |
Development | 开发 | 600 | 750 |
Analysis | 需求分析 (包括学习新技术) | 100 | 150 |
Design Spec | 生成设计文档 | 60 | 75 |
Design Review | 设计复审 | 30 | 45 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 40 |
Design | 具体设计 | 60 | 90 |
Coding | 具体编码 | 300 | 350 |
Code Review | 代码复审 | 45 | 60 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 75 |
Reporting | 报告 | 90 | 60 |
Test Repor | 测试报告 | 30 | 20 |
Size Measurement | 计算工作量 | 15 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 45 | 30 |
合计 | 750 | 850 |
解题思路描述
实现一个具有简单图形化界面的计算器
1、编程语言选择Java,前端做的固然花里胡哨,但是本人Java都还没学明白
2、UI设计比较简陋,主打的就是看的过去就行
3、核心功能:实现最简单的加减乘除、开根、乘方运算,三角函数运算顺序的设计是最难的,但本人技术不佳,查阅很多博客,也问了朋友,只得到粗略解决,用Math库函数来计算
4、
设计与实现过程
项目利用Java中的GUI库——Swing来实现
1、将所有要实现的按键封装在一个KEYS数组中,新建一个JButton按钮组件,并插入JTextField文本框用以实现最终的结果
private String[] KEYS={"7","8","9","*","4","5","6","÷","1","2","3","+","0","e","π","-","c","%",".","=","(",")","sqrt","x**2","sin","cos","tan"};
private JButton keys[]=new JButton[KEYS.length];
private JTextField Operand_resultText = new JTextField("0.0");
private String b="";
2、编写简易计算器界面,设置输入框以及各个按键的位置(只做到了看起来尽量整齐),并未每一个按钮添加响应事件(用事件监听器ActionListener接收)
public Calculation()
{
super("铄哥的计算器");
this.setLayout(null);
//设置计算机输入框的大小和位置
Operand_resultText.setBounds(20, 5, 255, 40);
//设置计算机输入框的数字水平靠右
Operand_resultText.setHorizontalAlignment(JTextField.RIGHT);
//设置计算机输入框可编辑
Operand_resultText.setEditable(false);
this.add(Operand_resultText);
//设置计算机的按钮
int x=20,y=55;
for (int i=0;i<KEYS.length;i++)
{
keys[i] = new JButton();
keys[i].setText(KEYS[i]);//设置按钮上的标签,1-9,+,-,*,/.....
keys[i].setBounds(x, y, 60, 40);
//设置每个按钮的位置
if(x<215)
{
x+=65;
}
else
{
x = 20;
y+=45;
}
this.add(keys[i]);
}
//为每一个按钮添加响应事件
for (int i = 0; i <KEYS.length; i++)
{
keys[i].addActionListener(this);
}
//关于简易计算机的其他设置
this.setResizable(false);
this.setBounds(500, 200, 300, 430);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
3、组件发送操作时调用的方法,在此用以对用户输入的算术表达式进行响应
public void actionPerformed(ActionEvent e)
{
//获取响应事件的label
String label = e.getActionCommand();
//根据不同的label给出计算结果
if (label=="c"||label=="=")
{
//如果触犯事件为=, 那么就执行输入框中的前面输入的 运算式子
if(label=="=")
{
String s[]=Operation(this.b);
String Operand_result=Operand_result(s);
this.b=Operand_result+"";
Operand_resultText.setText(this.b);
}
//如果触发事件是c,那么就是清空当前的输入框
else
{
this.b="";
Operand_resultText.setText("0");
}
}
//平方根计算
else if (label=="sqrt")
{
String result=square(this.b);
Operand_resultText.setText(result);
this.b=result;
}
//平方计算
else if(label=="x**2")
{
String result=Sqrt(this.b);
Operand_resultText.setText(result);
this.b=result;
}
else if(label=="e"||label=="π")
{
if (label=="e")
{
String m=String.valueOf(2.71828);
this.b=this.b+m;
Operand_resultText.setText(this.b);
}
if (label=="π")
{
String m=String.valueOf(3.14159265);
this.b=this.b+m;
Operand_resultText.setText(this.b);
}
}
else
{
this.b=this.b+label;
Operand_resultText.setText(this.b);
}
}
4、用之前学过的栈来处理运算表达式,先将字符压入栈,按优先级计算
private String[] Operation(String str)
{
String s="";
char a[]=new char[100];
String cal_resutl[]=new String[100];
int top=-1,j=0;
for (int i=0;i<str.length();i++)
{
if ("0123456789.".indexOf(str.charAt(i))>=0)
{
s="";
for (;i<str.length()&&"0123456789.".indexOf(str.charAt(i))>=0;i++)
{
s=s+str.charAt(i);
}
i--;
cal_resutl[j]=s;
j++;
}
else if ("(".indexOf(str.charAt(i))>=0)
{
top++;
a[top]=str.charAt(i);
}
else if (")".indexOf(str.charAt(i))>=0)
{
for (;;)
{
if (a[top]!='(')
{
cal_resutl[j]=a[top]+"";
j++;
top--;
}
else
{
top--;
break;
}
}
}
else if ("*%÷".indexOf(str.charAt(i))>=0)
{
if (top==-1)
{
top++;
a[top]=str.charAt(i);
}
else
{
if ("*%÷".indexOf(a[top])>=0)
{
cal_resutl[j]=a[top]+"";
j++;
a[top]=str.charAt(i);
}
else if ("(".indexOf(a[top])>=0)
{
top++;
a[top]=str.charAt(i);
}
else if ("+-".indexOf(a[top])>=0)
{
top++;
a[top]=str.charAt(i);
}
}
}
else if ("+-".indexOf(str.charAt(i))>=0)
{
if (top==-1)
{
top++;
a[top]=str.charAt(i);
}
else
{
if ("%*÷".indexOf(a[top])>=0)
{
cal_resutl[j]=a[top]+"";
j++;
a[top]=str.charAt(i);
}
else if ("(".indexOf(a[top])>=0)
{
top++;
a[top]=str.charAt(i);
}
else if ("+-".indexOf(a[top])>=0)
{
cal_resutl[j]=a[top]+"";
j++;
a[top]=str.charAt(i);
}
}
}
}
for (;top!=-1;)
{
cal_resutl[j]=a[top]+"";
j++;
top--;
}
return cal_resutl;
}
5、用刚开始创建的JTextField文本框返回和显示运算结果
public String Operand_result(String str[])
{
//限定只能输入100个字符
String Operand_result[]=new String[100];
int Top=-1;
for (int i=0;str[i]!=null;i++)
{
if ("+-*%÷".indexOf(str[i])<0)
{
Top++;
Operand_result[Top]=str[i];
}
if ("+-*%÷".indexOf(str[i])>=0)
{
double x,y,n;
x=Double.parseDouble(Operand_result[Top]);
Top--;
y=Double.parseDouble(Operand_result[Top]);
Top--;
if ("-".indexOf(str[i])>=0)
{
n=y-x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
if ("+".indexOf(str[i])>=0)
{
n=y+x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
if ("*".indexOf(str[i])>=0)
{
n=y*x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
if ("÷".indexOf(str[i])>=0)
{
if (x==0)
{
String s="ERROR";
return s;
}
else
{
n=y/x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
}
if ("%".indexOf(str[i])>=0)
{
if (x==0)
{
String s="ERROR";
return s;
}
else
{
n=y%x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
}
}
}
return Operand_result[Top];
}
程序性能改进
1、本来没有想实现最简单的功能,但是看到大家都有三角函数的功能,就调了Math库的库函数直接计算输入的数的三角函数值
else if (label=="sin")
{
String result= String.valueOf(Math.sin( Double.parseDouble(this.b)) );
Operand_resultText.setText(result);
this.b=result;
}
else if (label=="cos")
{
String result= String.valueOf(Math.cos( Double.parseDouble(this.b)) );
Operand_resultText.setText(result);
this.b=result;
}
else if (label=="tan")
{
String result= String.valueOf(Math.tan( Double.parseDouble(this.b)) );
Operand_resultText.setText(result);
this.b=result;
}
2、
单元测试
利用Junit对其中的几个函数进行测试
异常处理
输入异常数据或除数、取余数子为零时,通过if语句判断后在弹窗进行报错,显示面板显示ERROR
if ("÷".indexOf(str[i])>=0)
{
if (x==0)
{
String s="ERROR";
return s;
}
else
{
n=y/x;
Top++;
Operand_result[Top]=String.valueOf(n);
}
}
if ("%".indexOf(str[i])>=0)
{
if (x==0)
{
String s="ERROR";
return s;
}
心得体会
在本次大作业中,我了解了Java下的GUI库,并用其实现图形化界面,顺带复习了一下运算表达式的书写。以及第一次使用Junit进行单元测试、将Java文件转化成exe文件,还去社区上搜索了教程,可谓波折,深刻感受到了这一套流程下来的不容易。