CoderZQYのBlog

个人不定期更新的学习周报

0%

Android_Calculator

Java课程设计——基于Android的计算器实现

1、基本要求

​ 功能:完成一个基本的计算器程序。界面可以是GUI方式,也可以是字符形式的命令行方式。能实现:加、减、乘、除、乘方(使用符号^)及括号的运算。运行对象是整数(能实现GUI界面的且带小数点的实数运算可以晋升为良好级别。)

2、系统需求分析

​ Android是以Linux为核心的手机操作平台,作为一款开放式的操作系统,随着Android的快速发展,如今已允许开发者使用多种编程语言来开发Android应用程序了,而不再是以前只能用Java开发Android应用程序的单一局面,因而受到众多开发者的欢迎,成为真正意义上的开放式操作系统。

​ 计算器通过算法实行简单的数学计算从而提高了数学计算的效率,实现计算器的界面优化,使界面更加友好,操作更加方便。基于Android的计算器的设计,系统既有良好的界面、必要的交互信息,从而达到简约美观的效果。使用人员能快捷简单地进行操作,即可单击按钮进行操作,即时准确地获得需要的计算结果,充分降低了数学计算的难度,从而节约了时间。

3、总体设计

3.1 程序功能概要设计

根据需求,符合用户的实际要求,系统应实现以下功能:友好的界面、方便使用;具有基本的加、减、乘、除以及乘方功能,支持小括号更改优先级,能够判断用户输入运算数是否正确,支持小数运算和清除功能

img

3.2 程序系统结构

​ 程序基于Android技术开发,除总体模块外,主要分为输入模块、显示模块以及运算模块三大部分。在整个系统中总体模块控制系统的生命周期,输入模块部分负责读取用户输入的数据,显示模块部分负责显示用户之前输入的数据以及最终的计算结果,计算模块部分负责进行数据的运算以及一些其他的功能,具体地说,总体模块的作用主要是生成应用程序的主类,控制应用程序的周期。

  • 输入模块主要描述了计算器键盘以及键盘的监听即主要负责读取用户的键盘输入以及响应触屏的按键,需要监听手机动作。同时提供较为直观的键盘图形用户界面。

  • 显示模块描述了计算器的显示区,即该区域用于显示用户输入的数据以及最终的计算结果,同时负责显示一些其他的信息。

  • 计算模块则主要描述了计算器的整体,实现了计算器的界面,负责计算用户输入数据,包括加、减、乘、除、乘方等各种功能,记忆数据的相关功能、优先级判定的功能和清零的功能。

img

3.3 算法设计

  1. 输入包含+、-、×、÷、圆括号和实数组成的中缀算术表达式,以 ‘@’ 作为表达式的结束符,计算表达式的运算结果返回。

  2. 中缀表达式求值算法

    首先必须设置两个栈:一个栈存放操作符,记作OPTR;另一个栈存放操作数,记作OPND。

    初始时,操作数栈为空,操作符栈中有一个元素 ‘@’ 。在进行表达式求值时,从左到右扫描,依次读入表达式中的每个字符,直至表达式结束。

    • 若读到的是操作数,则一律进入操作数栈,并读入下一个字符(若要处理实数,需创建一个方法进行处理,将读取到的实数入栈)。

    • 若读到的是操作符c,则应用操作符栈的栈顶元素pre_op与之进行比较,会出现以下3种情况:

      ① 若pre_op < c,则将c入栈,读入下一个字符。

      ② 若pre_op = c,则将pre_op出栈,并读入下一个字符。

      ③ 若pre_op > c,则将pre_op出栈,并在操作数栈中退栈2次,依次得到操作数b、a(注意操作数次序)。然后进行a pre_op b运算,并将运算的结果压入操作数栈中。

  3. 扫描完毕时,操作数栈中只有一个元素,即为运算的结果。

  4. 若输入表达式违法,则返回 “Error!” 结果。

4、代码实现

4.1 Calculator类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package com.example.calculator;

import java.util.Stack;

/**
* Description:计算器类,对表达式求值
*/
public class Calculator {
/**
* 计算表达式的值
* @return 表达式结果
*/
private static int index;

public static float calculate(String expression) {
//System.out.println(expression);
// 新建两个栈,一个存储数据,一个存储操作符
Stack<Float> numStack = new Stack<>();
Stack<Character> operStack = new Stack<>();
operStack.push('@');
// 初始化
expression += "@"; //表达式以@作为结束标志
index = 0;
char[] expToChar = expression.toCharArray();
char ch;
while(!operStack.isEmpty()){
ch = expToChar[index];
if(isDigit(ch)){
readNum(numStack,expToChar); //读取一个实数入栈
} else {
char pre_op = operStack.peek();
switch (precede(pre_op, ch)) {
case '<':
operStack.push(ch);
index++;
break;
case '=':
operStack.pop();
index++;
break;
case '>':
float a = numStack.pop();
float b = numStack.pop();
pre_op = operStack.pop();
numStack.push(operate(a, pre_op, b));
break;
}
}
}
return numStack.peek();
}

/**
* 判断是否是数字
* @param ch 要判断的字符
* @return
*/
private static boolean isDigit(char ch){
if(ch >= '0' && ch <= '9'){
return true;
}else {
return false;
}
}

/**
* 从表达式中读取实数并入操作数栈
* @param numStack
* @param expToChar
*/
private static void readNum(Stack<Float> numStack, char[] expToChar) {
numStack.push((float) expToChar[index] - '0');
index++;
while (isDigit(expToChar[index])) {
numStack.push(numStack.pop() * 10 + (float) expToChar[index] - '0');
index++;
}
if ('.' == (expToChar[index])) {
index++;
float cost = 1;
while (isDigit(expToChar[index])) {
numStack.push(numStack.pop() + (float) (expToChar[index] - '0') * (cost /= 10));
index++;
}
}
}

/**
*
* @param f1 操作数
* @param pre_op 运算符
* @param f2 操作数
* @return 运算结果
*/
private static float operate(float f1, char pre_op, float f2) {
switch(pre_op) {
case '+':
return f1+f2;
case '-':
return f2-f1;
case '×':
return f2*f1;
case '÷':
return f2/f1;
case '^':
return (float) Math.pow(f2, f1);
default:
throw new RuntimeException("输入错误");
}
}

/**
* 获取运算符优先级
* @param pre_op 栈顶的操作符
* @param ch 新的操作符
* @return 运算符优先级
*/
private static char precede(char pre_op, char ch) {
char[][] pri = new char[][]{
{ '>', '>', '<', '<', '<', '<', '>', '>' },
{ '>', '>', '<', '<', '<', '<', '>', '>' },
{ '>', '>', '>', '>', '<', '<', '>', '>' },
{ '>', '>', '>', '>', '<', '<', '>', '>' },
{ '>', '>', '>', '>', '>', '<', '>', '>' },
{ '<', '<', '<', '<', '<', '<', '=', ' ' },
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
{ '<', '<', '<', '<', '<', '<', ' ', '=' },
};
return pri[transfer(pre_op)][transfer(ch)];
}

/**
* 将运算符转换为对应的优先级数组的下标
* @param c 运算符
* @return 对应优先级数组的下标
*/
public static int transfer(char c) {
switch (c) {
case '+':
return 0;
case '-':
return 1;
case '×':
return 2;
case '÷':
return 3;
case '^':
return 4;
case '(':
return 5;
case ')':
return 6;
case '@':
return 7;
default:
throw new RuntimeException("数字输入错误");
}
}
}

4.2 activity_main.xml布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:background="#000000">

<EditText
android:layout_marginTop="10dp"
android:id="@+id/et_input"
android:layout_width="350dp"
android:layout_height="60dp"
android:background="@drawable/white"
android:textSize="40sp"
android:layout_gravity="center_horizontal"/>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:gravity="center_horizontal">

<Button
android:id="@+id/btn_clr"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="C"
android:textSize="30sp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>

<Button
android:id="@+id/btn_div"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="÷"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>

<Button
android:id="@+id/btn_mul"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="×"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>
<Button
android:id="@+id/btn_del"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="⬅"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:gravity="center_horizontal"
>
<Button
android:id="@+id/btn_pow"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="^"
android:textSize="30sp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>

<Button
android:id="@+id/btn_lb"
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/blue"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:text="("
android:textSize="30sp" />

<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/btn_rb"
android:text=")"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>
<Button
android:id="@+id/btn_sub"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="-"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue" />
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal"
android:gravity="center_horizontal"
>
<Button
android:id="@+id/btn_7"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="7"
android:textSize="30sp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
<Button
android:id="@+id/btn_8"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="8"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
<Button
android:id="@+id/btn_9"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="9"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
<Button
android:id="@+id/btn_add"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="+"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/blue"/>
</LinearLayout>

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:gravity="center_horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_4"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="4"
android:textSize="30sp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
<Button
android:id="@+id/btn_5"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="5"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
<Button
android:id="@+id/btn_6"
android:layout_width="80dp"
android:layout_height="80dp"
android:text="6"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/btn_1"
android:text="1"
android:textSize="30sp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector" />
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/btn_2"
android:text="2"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector" />
<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/btn_3"
android:text="3"
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector" />
</LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10dp">

<Button
android:id="@+id/btn_0"
android:layout_width="170dp"
android:layout_height="80dp"
android:background="@drawable/selector"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:text="0"
android:textSize="30sp" />

<Button
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/btn_pt"
android:text="."
android:textSize="30sp"
android:layout_marginLeft="10dp"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:background="@drawable/selector"/>

</LinearLayout>

</LinearLayout>

<Button
android:id="@+id/btn_eq"
android:layout_width="80dp"
android:layout_height="260dp"
android:layout_marginLeft="10dp"
android:background="@drawable/button_bg"
android:paddingRight="15sp"
android:paddingBottom="15sp"
android:text="="
android:textSize="30sp" />

</LinearLayout>

</LinearLayout>

4.3 MainActivity类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package com.example.calculator;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//创建Button对象(也就是activity_main.xml里所设置的ID)
Button btn_0,btn_1,btn_2,btn_3,btn_4,btn_5,btn_6,btn_7,btn_8,btn_9,btn_pt;
Button btn_mul,btn_div,btn_add,btn_sub,btn_pow,btn_lb,btn_rb;
Button btn_clr,btn_del,btn_eq;
EditText et_input;
boolean clr_flag; //判断et编辑文本框中是否清空

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//实例化对象
setContentView(R.layout.activity_main);//客观存在,还没有在UI上显示
btn_0= (Button) findViewById(R.id.btn_0);
btn_1= (Button) findViewById(R.id.btn_1);
btn_2= (Button) findViewById(R.id.btn_2);
btn_3= (Button) findViewById(R.id.btn_3);
btn_4= (Button) findViewById(R.id.btn_4);
btn_5= (Button) findViewById(R.id.btn_5);
btn_6= (Button) findViewById(R.id.btn_6);
btn_7= (Button) findViewById(R.id.btn_7);
btn_8= (Button) findViewById(R.id.btn_8);
btn_9= (Button) findViewById(R.id.btn_9);
btn_pt= (Button) findViewById(R.id.btn_pt);
btn_add= (Button) findViewById(R.id.btn_add);
btn_sub= (Button) findViewById(R.id.btn_sub);
btn_mul= (Button) findViewById(R.id.btn_mul);
btn_div= (Button) findViewById(R.id.btn_div);
btn_clr= (Button) findViewById(R.id.btn_clr);
btn_del= (Button) findViewById(R.id.btn_del);
btn_eq= (Button) findViewById(R.id.btn_eq);
btn_pow=(Button) findViewById(R.id.btn_pow);
btn_lb=(Button) findViewById(R.id.btn_lb);
btn_rb=(Button) findViewById(R.id.btn_rb);
et_input= (EditText) findViewById(R.id.et_input);
//给按钮设置的点击事件
btn_0.setOnClickListener(this);
btn_1.setOnClickListener(this);
btn_2.setOnClickListener(this);
btn_3.setOnClickListener(this);
btn_4.setOnClickListener(this);
btn_5.setOnClickListener(this);
btn_6.setOnClickListener(this);
btn_7.setOnClickListener(this);
btn_8.setOnClickListener(this);
btn_9.setOnClickListener(this);
btn_pt.setOnClickListener(this);
btn_add.setOnClickListener(this);
btn_sub.setOnClickListener(this);
btn_mul.setOnClickListener(this);
btn_div.setOnClickListener(this);
btn_clr.setOnClickListener(this);
btn_del.setOnClickListener(this);
btn_eq.setOnClickListener(this);
btn_pow.setOnClickListener(this);
btn_lb.setOnClickListener(this);
btn_rb.setOnClickListener(this);
}

@Override
public void onClick(View v) {
String str = et_input.getText().toString();
switch (v.getId()){
case R.id.btn_0:
case R.id.btn_1:
case R.id.btn_2:
case R.id.btn_3:
case R.id.btn_4:
case R.id.btn_5:
case R.id.btn_6:
case R.id.btn_7:
case R.id.btn_8:
case R.id.btn_9:
case R.id.btn_pt:
case R.id.btn_add:
case R.id.btn_sub:
case R.id.btn_mul:
case R.id.btn_div:
case R.id.btn_pow:
case R.id.btn_lb:
case R.id.btn_rb:
if(clr_flag){
clr_flag=false;
str="";
et_input.setText("");
}
et_input.setText(str + ((Button)v).getText());
break;
case R.id.btn_clr:
if(clr_flag){
clr_flag=false;
}
et_input.setText("");
break;
case R.id.btn_del:
if(clr_flag){
clr_flag = false;
et_input.setText("");
} else if(!str.equals("")){
et_input.setText(str.substring(0,str.length()-1));
}
break;
case R.id.btn_eq: //运算得出最后结果
System.out.println(str);
if(!str.equals("")){
String rs = "";
try{
rs = String.valueOf(Calculator.calculate(str));
}catch (Exception e){
rs = "ERROR!";
e.printStackTrace();
}finally {
et_input.setText(rs);
clr_flag = true;
}
}
break;
}
}
}

5、实现效果

image-20210317120555060

image-20210317120614431

image-20210317120629719

更多请联系QQ:1277565476

-------------本文结束感谢您的阅读-------------