最近发现我在CSDN里面分享的一些文件都被提高积分了,有的提高的有点夸张。所以以后我尽量把代码在博客里面贴全。
代码下载。
github地址:https://github.com/AtaoistPriest/Calculator
如果积分不够,复制以下代码也可以。当然欢迎积分下载。
这几天时间比较充裕,我用Android实现了一个计算器,以前也实现过,但那个版本功能简单,代码论乱,不易理解,关键是还有BUG。所以,我完善一下。实现计算器的难点主要是,输入算式时的排错和最后根据算术表达式求出数值。因为有括号,运算符优先级等问题,所以还是有点难度的。
计算器的界面如下:
好了,下面开始了。
界面布局文件:activity_main.xml
接下来是程序入口MainActivity.java
package com.example.ffy.orginal;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements View.OnClickListener {
private TextView equationText,resultText;
private Button buttons[] = new Button[26];
private CheckInput checkInput;
private CounterByEquation counterByEquation;
//布局中所有按钮的ID
private int buttonIds[] = new int[]{
R.id.CE,R.id.BACKSPACE,R.id.Remainder,R.id.Involution,R.id.LBracket,R.id.RBracket,R.id.Factorial,
R.id.Reciprocal,R.id.P,R.id.E, R.id.Divide,R.id.N7,R.id.N8,R.id.N9,R.id.Multiply,R.id.N4,
R.id.N5,R.id.N6,R.id.Subtract,R.id.N1,R.id.N2,R.id.N3,R.id.Equal,R.id.Zero,R.id.Point, R.id.Add
};
//等式
private String equation = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init(); //初始化控件
}
/*
* 点击计算器键盘
*
* */
@Override
public void onClick(View v) {
int id = v.getId();
Button button = (Button)findViewById(id);
String text = button.getText().toString();
switch (id){
/*
* 按数字按钮
* */
case R.id.N1:
case R.id.N2:
case R.id.N3:
case R.id.N4:
case R.id.N5:
case R.id.N6:
case R.id.N7:
case R.id.N8:
case R.id.N9:
case R.id.Zero:
checkInput.setEquation(equation);
if(checkInput.checkNumberInput()){
equation = checkInput.getEquation();
equation += text;
}
break;
/*
* 点击 + - * /
* */
case R.id.Add:
case R.id.Subtract:
case R.id.Multiply:
case R.id.Divide:
checkInput.setEquation(equation);
if(checkInput.checkOperationsInput()){
equation = checkInput.getEquation();
equation += text;
}
break;
/*
* 点击退格键
*
* */
case R.id.BACKSPACE:
checkInput.setEquation(equation);
checkInput.backSpace();
equation = checkInput.getEquation();
break;
/*
* 点击 x^y
* */
case R.id.Involution:
checkInput.setEquation(equation);
if(checkInput.checkInvolutionInput())
equation+="^";
break;
/*
* 倒数
* */
case R.id.Reciprocal:
checkInput.setEquation(equation);
if(checkInput.checkReciprocalInput())
equation+="^(-1)";
break;
/*
* 左括号
* */
case R.id.LBracket:
checkInput.setEquation(equation);
if(checkInput.checkLBracketInput())
equation+="(";
break;
/*
* 右括号
* */
case R.id.RBracket:
checkInput.setEquation(equation);
if(checkInput.checkRBracketInput())
equation+=')';
break;
/*
* 取余
* */
case R.id.Remainder:
checkInput.setEquation(equation);
if(checkInput.checkRemainderInput())
equation+='%';
break;
/*
* 求阶乘
* */
case R.id.Factorial:
checkInput.setEquation(equation);
if(checkInput.checkFactorialInput())
equation+='!';
break;
/*
* 清空按钮
* */
case R.id.CE:
equation = "";
resultText.setText("");
break;
/*
* 小数点按钮
* */
case R.id.Point:
checkInput.setEquation(equation);
if(checkInput.checkPointInput()){
equation = checkInput.getEquation();
equation+=text;
}
break;
/*
* 点击π
* */
case R.id.P:
checkInput.setEquation(equation);
if (checkInput.checkSpecialSymbolBack()){
equation+="π";
}
break;
/*
* 点击e
* */
case R.id.E:
checkInput.setEquation(equation);
if (checkInput.checkSpecialSymbolBack()){
equation+="e";
}
break;
case R.id.Equal:
resultText.setText(new CounterByEquation(equation).solveEquation());
break;
}
equationText.setText(equation);
}
/*
* init()初始化绑定所有的控件,并添加事件
* */
void init(){
int length = buttons.length;
for(int i=0;i
接下来是输入排错的功能,CheckInput.java.主要是加各种约束。
package com.example.ffy.orginal;
public class CheckInput {
private String equation;
public void setEquation(String equation){
this.equation = equation;
}
public String getEquation(){
return equation;
}
/*
* 检查特殊符号输入问题,π或e,类似1e,2e,3e这样的按照出错处理
* */
boolean checkSpecialSymbolBack(){
int length = equation.length();
if(length==0) return true;
char perChar = equation.charAt(length-1); //获取前一位字符
if(perChar=='+'||perChar=='-'||perChar=='*'||perChar=='/') return true;
return false;
}
/*
* 检查输入数字
* */
boolean checkNumberInput(){
int length = equation.length();
if(length==0) return true;
char perChar = equation.charAt(length-1);
//避免出现 π1,e1,)1现象
if(perChar=='π'||perChar=='e'||perChar==')'||perChar=='!') return false;
//避免出现01,+001,2^00002等现象
if(length==1&&perChar=='0') equation = "";
if(length>1){
char perPerChar = equation.charAt(length-2);
if((perPerChar=='+'||perPerChar=='-'||perPerChar=='*'||perPerChar=='/'||perPerChar=='^')&&perChar=='0'){
equation = equation.substring(0,length-1);
}
}
return true;
}
/*
*小数点输入检查
* */
boolean checkPointInput(){
int length = equation.length();
//自动补0
if(length==0) equation+="0";
char perChar = equation.charAt(length-1);
//自动补0
if(perChar=='+'||perChar=='-'||perChar=='*'||perChar=='/'||perChar=='%') equation+="0";
if(perChar=='π'||perChar=='e'||perChar==')'||perChar=='('||perChar=='^'||perChar=='!') return false;
int pointNum = 0;
for(int i = length-1;i>=0;i--){
char checkChar = equation.charAt(i);
if(checkChar=='.') pointNum++;
if(checkChar=='^') return false;
if(checkChar=='+'||checkChar=='-'||checkChar=='*'||checkChar=='/'||checkChar=='%') break;
}
if(pointNum>0) return false;
return true;
}
/*
* 输入+ - * / 时进行检查,在他们的前面不能有 .和%
* */
boolean checkOperationsInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
if(perChar=='%'||perChar=='.'||perChar=='^'||perChar=='!'||perChar=='(') return false;
//替换
if(perChar=='+'||perChar=='-'||perChar=='*'||perChar=='/')
equation = equation.substring(0,length-1);
return true;
}
/*
* 退格处理
* */
void backSpace(){
int length = equation.length();
if(length==0) return;
char charPer = equation.charAt(length-1);
equation = equation.substring(0,length-1);
}
/*
* 检查 x^y
* */
boolean checkInvolutionInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
if(perChar!='1'&&perChar!='2'&&perChar!='3'&&perChar!='4'&&perChar!='5'&&perChar!='6'&&perChar!='7'
&&perChar!='8'&&perChar!='9'&&perChar!=')'&&perChar!='e'&&perChar!='π'&&perChar!='0') return false;
//一个式子里只能有 ^
int iNum = 0;
for(int i = length-1;i>0;i--){
char iChar = equation.charAt(i);
if(iChar=='^') iNum++;
if (iChar=='+'||iChar=='-'||iChar=='*'||iChar=='/'||iChar=='%') break;
}
if(iNum>0) return false;
return true;
}
/*
* 倒数
* */
boolean checkReciprocalInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
if(perChar!='1'&&perChar!='2'&&perChar!='3'&&perChar!='4'&&perChar!='5'&&perChar!='6'&&perChar!='7'
&&perChar!='8'&&perChar!='9'&&perChar!=')'&&perChar!='0') return false;
//单独一个0不能求倒数
int iNum = 0;
for(int i = length-1;i>=0;i--){
char iChar = equation.charAt(i);
iNum++;
if (iChar=='+'||iChar=='-'||iChar=='*'||iChar=='/'||iChar=='%') break;
}
if(iNum==1&&perChar=='0') return false;
return true;
}
/*
* 输入左括号
* */
boolean checkLBracketInput(){
int length = equation.length();
if(length==0) return true;
char perChar = equation.charAt(length-1);
if(perChar=='+'||perChar=='-'||perChar=='*'||perChar=='/'||perChar=='%'||perChar=='^'||perChar=='(') return true;
return false;
}
/*
* 输入右括号
* */
boolean checkRBracketInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
//左右符号要匹配
int lNum = 0,rNum = 0;
for(int i = length-1;i>=0;i--){
char checkChar = equation.charAt(i);
if(checkChar=='(') lNum++;
if(checkChar==')') rNum++;
if(lNum-rNum==1) break;
}
if((lNum-rNum==1)&&(perChar=='1'||perChar=='2'||perChar=='3'||perChar=='4'||perChar=='5'||perChar=='6'||perChar=='7'
||perChar=='8'||perChar=='9'||perChar=='0'||perChar==')')) return true;
return false;
}
/*
* 取余
* */
boolean checkRemainderInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
if(perChar=='1'||perChar=='2'||perChar=='3'||perChar=='4'||perChar=='5'||perChar=='6'||perChar=='7'
||perChar=='8'||perChar=='9'||perChar==')') return true;
return false;
}
/*
* 求阶乘
* */
boolean checkFactorialInput(){
int length = equation.length();
if(length==0) return false;
char perChar = equation.charAt(length-1);
if(perChar=='!'||perChar=='%'||perChar=='^'||perChar=='('||perChar=='+'
||perChar=='-'||perChar=='*'||perChar=='/') return false;
//小数点阶乘不可以存在
for(int i=length-1;i>=0;i--){
char checkChar = equation.charAt(i);
if(checkChar=='.') return false;
if(checkChar=='+'||checkChar=='-'||checkChar=='*'||checkChar=='/') break;
}
return true;
}
}
最后是根据算术表达式求出最终结果。主要思路是,先转换为后缀表达式,再根据后缀表达式求值。CounterByEquation.java
package com.example.ffy.orginal;
import android.util.Log;
import java.util.Stack;
import java.util.Queue;
public class CounterByEquation {
private String equation;
private Stack stack; //存储符号
private String []queue = new String[50]; //接受中缀表达式
private int count=0;
public CounterByEquation(String equation){
this.equation = equation;
}
/*
* ( ) * - / + ^ ! x^(-1) % e π 3.11 5
*
* ((3^5)+5^(-1)+((6%4)+e)*6)*2
* 3^5 5^-1 + 6%4 e + 6 * +
* */
String solveEquation(){
int length = equation.length();
/*
* 由中缀表达式求后缀表达式
* */
stack = new Stack<>();
for(int i=0;i0){
sum *= (num--);
}
queue[i] = sum+"";
continue;
}
if(member.equals("π")) {
queue[i] = "3.1415926";
continue;
}
if(member.equals("e")) {
queue[i] = "2.71828183";
continue;
}
if(member.equals("+")||member.equals("-")||member.equals("*")||member.equals("/")||member.equals("%")||member.equals("^")){
double first = Double.parseDouble(queue[i-2]);
double second = 0;
if(!queue[i-1].equals("-"))
second = Double.parseDouble(queue[i-1]);
if (member.equals("+")) first += second;
if (member.equals("-")){
//处理 x^(-1)的情况
if(queue[i+1]!=null&&queue[i+1].equals("^")){
first = 1 / first;
//为了不影响接下来的运算,在数组去除^
for(int j = i+1;j0;j--){
sum*=first;
}
first = sum;
}
queue[i-2] = first+"";
//前移
for(int j = i-1;j