赞
踩
最近发现我在CSDN里面分享的一些文件都被提高积分了,有的提高的有点夸张。所以以后我尽量把代码在博客里面贴全。
代码下载。
github地址:https://github.com/AtaoistPriest/Calculator
如果积分不够,复制以下代码也可以。当然欢迎积分下载。
这几天时间比较充裕,我用Android实现了一个计算器,以前也实现过,但那个版本功能简单,代码论乱,不易理解,关键是还有BUG。所以,我完善一下。实现计算器的难点主要是,输入算式时的排错和最后根据算术表达式求出数值。因为有括号,运算符优先级等问题,所以还是有点难度的。
计算器的界面如下:
好了,下面开始了。
界面布局文件:activity_main.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/Equation"
- android:textSize="16sp"
- android:hint="输入算式进行计算"
- android:layout_gravity="fill"
- android:maxLines="4"
- android:layout_marginTop="155sp"
- android:layout_alignParentTop="true"
- android:paddingRight="15sp"
- android:layout_columnSpan="4"
- android:gravity="right"/>
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/Equation"
- android:id="@+id/Result"
- android:textSize="16sp"
- android:hint="结果"
- android:layout_gravity="fill"
- android:maxLines="1"
- android:layout_marginTop="20sp"
- android:layout_marginBottom="15sp"
- android:paddingRight="15sp"
- android:layout_columnSpan="4"
- android:gravity="right"/>
- <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/Result"
- android:columnCount="4"
- android:layout_gravity="center"
- android:layout_marginLeft="13sp"
- android:orientation="horizontal">
- <Button
- android:id="@+id/CE"
- android:text="CE"
- android:textSize="15sp"
- android:layout_gravity="fill"
- android:layout_marginTop="35sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/BACKSPACE"
- android:text="BACKSPACE"
- android:textSize="15sp"
- android:layout_gravity="fill"
- android:layout_marginTop="35sp"
- android:layout_marginBottom="5sp"
- android:layout_marginRight="5sp"
- android:layout_columnSpan="2"
- />
- <Button
- android:id="@+id/Remainder"
- android:text="%"
- android:textSize="15sp"
- android:layout_marginTop="35sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Involution"
- android:text="x^y"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/LBracket"
- android:text="("
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/RBracket"
- android:text=")"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Factorial"
- android:text="X!"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Reciprocal"
- android:text="1/X"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/P"
- android:text="π"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/E"
- android:text="e"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Divide"
- android:text="/"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N7"
- android:text="7"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N8"
- android:text="8"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N9"
- android:text="9"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Multiply"
- android:text="*"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N4"
- android:text="4"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N5"
- android:text="5"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N6"
- android:text="6"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Subtract"
- android:text="-"
- android:textSize="15sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N1"
- android:text="1"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N2"
- android:text="2"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/N3"
- android:text="3"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- android:layout_marginBottom="5sp"
- />
- <Button
- android:id="@+id/Equal"
- android:text="="
- android:textSize="15sp"
- android:layout_gravity="fill_vertical"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_rowSpan="2"
- />
- <Button
- android:id="@+id/Zero"
- android:text="0"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- />
- <Button
- android:id="@+id/Point"
- android:text="."
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- />
- <Button
- android:id="@+id/Add"
- android:text="+"
- android:textSize="15sp"
- android:layout_marginRight="5sp"
- />
- </GridLayout>
- </RelativeLayout>
-
-

接下来是程序入口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<length;i++){
-
- buttons[i] = (Button)findViewById(buttonIds[i]);
- buttons[i].setOnClickListener(this);
- }
- equationText = (TextView)findViewById(R.id.Equation);
- resultText = (TextView)findViewById(R.id.Result);
- checkInput = new CheckInput();
- counterByEquation = new CounterByEquation(equation);
- }
- }

接下来是输入排错的功能,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<String> 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;i<length;i++){
-
- char curChar = equation.charAt(i);
- if(curChar=='('||curChar=='+'||curChar=='-'||curChar=='*'||curChar=='/'||curChar=='%'||curChar=='^'){
-
- String top = "";
- if(!stack.empty())
- top = stack.peek();
- if(curChar=='(') {
- stack.push(curChar+"");
- } else if (curChar == '%' || curChar == '^') {
- if(!stack.empty()&&(top.equals("^")||top.equals("%"))){
- queue[count++] = stack.pop();
- }
- stack.push(curChar+"");
-
- } else if ((curChar == '+' || curChar == '-')) {
- while (true) {
- if (stack.empty()) break;
- if (stack.peek().equals("(")) break;
- queue[count++] = stack.pop();
- }
- stack.push(curChar+"");
- } else if (curChar == '*' || curChar == '/') {
- if (!stack.empty()){
- while (true) {
- if (stack.peek().equals("*") || stack.peek().equals("/") || stack.peek().equals("%") || stack.peek().equals("^")) {
- queue[count++] = stack.pop();
- }else{
- break;
- }
- if (stack.empty()) break;
- if (stack.peek().equals("(")) break;
- }
- }
- stack.push(curChar+"");
- }
- }
- else if (curChar==')'){
- while(true){
- String tmp = stack.pop();
- if(tmp.equals("(")) break;
- else queue[count++] = tmp;
- }
- }
- else{ //数字
- String numStr = curChar+"";
- for(i++;i<length;i++)
- {
- char curBackChar = equation.charAt(i);
- if(curBackChar==')'||curBackChar=='+'||curBackChar=='-'||curBackChar=='*'||curBackChar=='/'||curBackChar=='%'||curBackChar=='^'){
- i--;
- break;
- }
- else
- numStr+=curBackChar;
- }
- queue[count++] = numStr;
-
- }
- }
-
- while(true){
- if(stack.empty()) break;
- queue[count++] = stack.pop();
- }
- String logStr = "";
- for(int i=0;i<count;i++){
- logStr+=queue[i]+" ";
- }
- Log.e("ERROR!!!!!!!!!!!!",logStr);
-
- /*由中缀表达式求值*/
- for(int i=0;i<count;i++){
- String member = queue[i];
- int numLength = member.length();
- if(member.charAt(numLength-1)=='!'){
- member = member.substring(0,numLength-1);
- int num = Integer.parseInt(member);
- int sum = 1;
- while(num>0){
- 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;j<count-1;j++)
- queue[j] = queue[j+1];
- count--;
- }else{
- first -= second;
- }
- }
- if (member.equals("*")) first *= second;
- if (member.equals("/")) first /= second;
- if (member.equals("%")) first %= second;
- if (member.equals("^")){
- double sum = 1;
- for(int j = (int)second;j>0;j--){
- sum*=first;
- }
- first = sum;
- }
- queue[i-2] = first+"";
- //前移
- for(int j = i-1;j<count-2;j++){
- queue[j] = queue[j+2];
- }
- count-=2;
- i-=2;
- }
- }
- return queue[0];
- }
-
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。