Android Studio开发实现简单计算器功能
短信预约 -IT技能 免费直播动态提醒
本文实例为大家分享了Android Studio开发实现简单计算器的具体代码,供大家参考,具体内容如下
代码:
activity_3.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".Activity3">
<RelativeLayout
android:id="@+id/r1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#1000"
tools:ignore="MissingConstraints">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text1"
android:layout_margin="6dp"
android:textSize="24sp"
android:text="">
</TextView>
<TextView
android:id="@+id/textv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:text="0"
android:padding="20dp"
android:textSize="30sp"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="100dp" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="22dp"
android:onClick="onClick"
android:text="%"
android:backgroundTint="#A67D3D"
android:textColor="#171616"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="22dp"
android:onClick="onClicka"
android:text="CE"
android:backgroundTint="#A67D3D"
android:textColor="#171616"
tools:ignore="OnClick" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="22dp"
android:onClick="onClick"
android:textAllCaps="false"
android:text="Back"
android:backgroundTint="#A67D3D"
android:textColor="#171616"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#E91E63"
android:backgroundTint="#8E2323"
android:onClick="onClick"
android:text="÷"
android:textSize="24dp"
app:backgroundTint="#2196F3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="1"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="2"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="3"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:backgroundTint="#8E2323"
android:onClick="onClick"
android:text="×"
android:textSize="24dp"
app:backgroundTint="#9C27B0" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="4"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="5"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="6"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="-"
android:backgroundTint="#8E2323"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="7"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="8"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="9"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="+"
android:backgroundTint="#8E2323"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:textSize="24dp"
android:onClick="onClick"
android:text="0"
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:textSize="24dp"
android:onClick="onClick"
android:text="."
android:backgroundTint="#0000FF"/>
<Button
android:layout_width="0dp"
android:textSize="30dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="onClick"
android:text="="
android:backgroundTint="#8E2323"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Activity3.java
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.math.BigDecimal;
import java.util.Stack;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Pattern;
public class Activity3 extends AppCompatActivity {
Stack<String> operator; //用于求解后缀表达式和计算
String memorry = "0"; //计算器M(R C + -)操作
int flag = 1; //判断是否要完全修改显示的值
boolean clearstr = false; //是否清除表达式的标志位
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_3);
operator = new Stack<>();
}
//此方法用于计算,操作数分别为a和b,运算符为opr
protected String operation(String a, String b, String opr){
String result = null; //存放运算结果
BigDecimal ope1 = new BigDecimal(a); //为了有较好的精度,选择BigDecimal对象进行计算
BigDecimal ope2 = new BigDecimal(b);
switch (opr){
case "+": result = ope1.add(ope2).stripTrailingZeros().toPlainString(); break; //stripTrailingZeros每一种运算都把小数点后多余的0去除
case "-": result = ope1.subtract(ope2).stripTrailingZeros().toPlainString(); break; //toPlainString不用科学计数法显示
case "×": result = ope1.multiply(ope2).stripTrailingZeros().toPlainString(); break;
case "÷":
try{
result = ope1.divide(ope2, 8, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString(); //保留8位小数,捕获异常
}catch (Exception e){
result = "错误";
}
break;
case "^": result = String.valueOf(Math.pow(Double.parseDouble(a), Double.parseDouble(b))); break; //计算X的Y次方
case "`": result = String.valueOf(Math.pow(Double.parseDouble(a), (1 / Double.parseDouble(b)))) ; break; //计算X的1/Y次方
}
if(result.equals("NaN") || result.equals("Infinity")) result = "错误"; //虽然java中无穷大和负数的开根号并不会出现错误,但为了方便操作,显示提醒用户错误
return replaces(result); //replaces方法去除多余的0
}
//方法重载
//由于BigDecimal对象并没有提供以下函数,所以重载方法,采用double类型计算,但会丢失精度
protected String operation(String a, String str){
double result = 1;
switch (str){
case "sin": result = Math.sin(Double.parseDouble(a)); break;
case "cos": result = Math.cos(Double.parseDouble(a)); break;
case "tan": result = Math.tan(Double.parseDouble(a)); break;
case "n!":
if(!a.contains("."))
for(int i = 2; i <= Integer.parseInt(a); i++){
result *= i;
} break;
}
return replaces(String.valueOf(result)); //replaces方法去除多余的0
}
//去掉多余的0
protected String replaces(String s){
if(s != null && s.indexOf(".") > 0){
s = s.replaceAll("0+?$", "");//去掉多余的0
s = s.replaceAll("[.]$", "");//如最后一位是.则去掉
}
return s;
}
//Java没有提供栈的清空函数,需要自己定义
protected void clearStack(Stack<String> operator){
while(!operator.isEmpty()){
operator.pop();
}
}
//求两个运算符的优先级的相对大小
protected int priority(String a, String b) {
int x = 0, y = 0;
switch(a) {
case "(": case ")":
x = 3; break;
case "^": case "`":
x = 2; break;
case "×": case "÷":
x = 1; break;
case "+": case "-":
x = 0; break;
}
switch(b) {
case "(": case ")":
y = 3; break;
case "^": case "`":
y = 2; break;
case "×": case "÷":
y = 1; break;
case "+": case "-":
y = 0; break;
}
return x - y;
}
//求后缀表达式
protected String bolan(ArrayList<String> array) {
StringBuffer stb = new StringBuffer(); //存放后缀表达式,需要频繁修改字符串,使用StringBuffer
Iterator<String> it = array.iterator(); //迭代器
Pattern pattern = Pattern.compile("[0-9]+.*[0-9]*"); //匹配非运算符的正则表达式
String op = null; //临时存放array数组内容
while(it.hasNext()) { //遍历数组
op = it.next().toString();
switch(op) {
case "(": operator.push(op); break;
case ")":
while(!operator.peek().equals("(")) {
stb.append(operator.pop() + " ");//pop()移除一个元素并将该元素返回
}
operator.pop(); break;
case "+": case "-": case "×": case "÷": case "^": case "`":
if(operator.isEmpty() || operator.peek().equals("(") || priority(op, operator.peek())>0) {
operator.push(op);
}else {
while(!operator.isEmpty() && priority(op, operator.peek()) <= 0 && !operator.peek().equals("(")) {
stb.append(operator.pop() + " ");
}
if(!operator.isEmpty() && operator.peek().equals("(")) operator.pop();
operator.push(op);
} break;
}
if(pattern.matcher(op).matches()) {
stb.append(op + " ");
}
}
while(!operator.isEmpty()) {
stb.append(operator.pop() + " ");
}
return stb.toString();
}
//判断字符是运算符还是数字的函数
protected boolean isOperator(char c) {
boolean flag = false;
switch(c) {
case '+': case '-': case '×': case '÷': case '(': case ')': case '^': case '`':flag = true; break;
}
return flag;
}
//把字符串切分到数组中
protected ArrayList<String> Split(String str) {
ArrayList<String> list = new ArrayList<>();
StringBuffer sbf = new StringBuffer();
if(str.charAt(0) == '-') str = '0' + str; //如果字符以负号开始,则在字符串头加入0
for(int i = 0; i < str.length(); i++) { //遍历所有字符
if(isOperator(str.charAt(i))) {
if(sbf.length()>0) list.add(sbf.toString()); //如果当前字符是运算符,把sbf的内容作为整体作为List的一项
sbf.delete(0, sbf.length()); //清空sbf的内容
list.add(String.valueOf(str.charAt(i)));
}else {
sbf.append(str.charAt(i)); //如果当前的字符不是运算符,就加入到sbf中,到下一个运算符出现为止,可以保证多位数的数字不被分割
}
}
if(sbf.length() > 0) list.add(sbf.toString()); //此时的sbf保存了最后一个操作数,应该加入List数组
return list;
}
//所有Button的绑定函数
public void onClick(View view){
Button btn = (Button) view; //接收到的参数转换为Button对象
TextView tv = (TextView) this.findViewById(R.id.textv); //获取TextView组件
TextView tv1 = (TextView) this.findViewById(R.id.text1);
String str = btn.getText().toString(); //获取按钮的文本以确定按下的是哪个按钮
String text = tv.getText().toString(); //获取显示框的文本
if(clearstr){
clearstr = false; //此位为真,需要把输入的表达式清空
tv1.setText("");
}
String totalstr = tv1.getText().toString(); //获取显示在左上角的表达式字符串
String result = null, a, b;
if(text.equals("错误")){ //出现除0错误后,无论点击哪个按钮都只做显示文本0的操作
clearStack(operator); //所有的点击操作都使计算器重置
tv.setText("0");
flag = 1;
return;
}
if(str.equals("x^y")){ //计算器按钮上的文本是多位字符,修改为一位方便操作
str = "^";
}else if(str.equals("x^1/y")){ //计算器按钮上的文本是多位字符,修改为一位方便操作
str = "`";
}
switch (str){
case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9":
if(flag == 1){ //flag为1,说明当前还没输入或上一次运算已经结束,不需要再保存当前显示的数字
result = str;
if(str.equals("0")){
flag = 1; //如果点击0,则flag保持不变,防止当前显示0的情况下点击0会出现多个0的情况
}else{
flag = 0; //如果点击的不是0,flag改为0
}
}else if(flag == 0){ //flag为0时,当前点击的数字直接加到文本显示的数字之后
result = text + str;
} break;
case "+": case "×": case "÷": case "^": case "`":
if(flag == 1){ //连续多次点击符号按钮,仅保留最后一次点击的符号
if(totalstr.length() > 0 && !totalstr.endsWith("(")){ //把上一次点击的符号去除后添加当前符号
int temp = totalstr.length();
totalstr = totalstr.substring(0, temp - 1) + str;
}
}else if(!totalstr.endsWith(")")){ //以)结尾,点击运算符后直接加入到表达式后面
totalstr = totalstr + text + str;
}else totalstr = totalstr + str; //点击了数字后又点了运算符,需要把数字和运算符都加入到表达式
tv1.setText(totalstr);
flag = 1;
break;
case "-":
if(totalstr.endsWith("(") && flag == 1){ //负数的输入需要在负号前加上0,方便操作的统一
totalstr = totalstr + "0" + str;
}else{
if(flag == 1){
if(totalstr.length() > 0){ // 重复点击了运算符,把上一次点击的符号去除后添加当前符号
int temp = totalstr.length();
totalstr = totalstr.substring(0, temp - 1) + str;
}else{ //负数的输入需要在负号前加上0,方便操作的统一
totalstr = "0" + str;
}
}else if(!totalstr.endsWith(")")){ //输入完了右括号,点击负号直接加入表达式,否则把当前输入的数字和负号一起加入表达式
totalstr = totalstr + text + str;
}else totalstr = totalstr + str;
}
tv1.setText(totalstr);
flag = 1;
break;
case "=":
//点击等号后把表达式转化成后缀表达式,并求值
clearStack(operator); //求值之前先清空栈,防止出现错误
if(!totalstr.endsWith(")")){ //如果不是以右括号结尾,说明当前输入的数并没有加入到表达式中,需要加入后再进行操作
totalstr = totalstr + text;
tv1.setText(totalstr);
}
try{
//运算过程中出现任何错误都在显示框中显示“错误”
for(String z:bolan(Split(totalstr)).split(" ")) { //z为后缀表达式的每一项
if(isOperator(z.charAt(0))) {
b = operator.pop();
a = operator.pop();
result = replaces(operation(a, b, z)); //出栈两个数进行运算
operator.push(result); //运算结果入栈
}else {
operator.push(z); //数字直接入栈
}
}
}catch (Exception e){
tv.setText("错误");
}
flag = 1; //点击等号后下次点击其他按钮需要清空表达式
clearstr = true; break;
case "(":
if(totalstr.length() > 0 && !Character.isDigit(totalstr.charAt(totalstr.length() - 1))){ //表达式非空且以运算符结尾直接加入
totalstr = totalstr + str;
}else if(totalstr.length() == 0) totalstr = str; //如果表达式为空,直接加入
tv1.setText(totalstr);
break;
case ")":
totalstr = totalstr + text + str; //把当前数字加上右括号加入到表达式
tv1.setText(totalstr);
break;
case "CE":
tv.setText("0"); //请零当前输入的数字
flag = 1;
break;
case "C":
tv1.setText(""); //重置
tv.setText("0");
flag = 1;
break;
case ".":
if(flag == 1){ //flag为1时,按下数字需要更改文本框显示按下的数字,按下小数点则显示0加小数点
result = "0.";
flag = 0;
}else if(!text.contains(".")){ //当前显示数字已经含有小数点,不进行任何操作,否则加上小数点
result = text + str;
}
break;
case "Back":
if(text.length() == 1 || flag == 1){ //如果只有1位或运算完成了,点击Back直接显示0
result = "0";
flag = 1;
}else{
int lenth = text.length();
result = text.substring(0, lenth - 1); //截取前n-1个字符
} break;
case "√X":
result = String.format("%f", Math.sqrt(Double.parseDouble(text))); //计算x平方根
if(result.equals("NaN")) result = "错误";
flag = 1;
result = replaces(result); //清除多余的0
break;
case "x²":
result = String.format("%f",Math.pow(Double.parseDouble(text), 2)); //计算x平方
result = replaces(result); //清除多余的0
flag = 1;
break;
case "1/x":
result = String.format("%f", 1 / Double.parseDouble(text));
if(result.equals("Infinity")) result = "错误"; //当出现1/0时结果为Infinity(无穷大),让计算器显示错误
flag = 1;
result = replaces(result);
break;
case "%":
result = operation(text, "100", "÷");
flag = 1;
break;
case "MR":
tv.setText(memorry); //显示内存里存储的数
flag = 1;
break;
case "MC":
memorry = "0"; //内存清零
flag = 1;
break;
case "M+":
memorry = operation(memorry, text, "+"); //内从中的数加上当前显示的数
break;
case "M-":
memorry = operation(memorry, text, "-"); //内从中的数减去当前显示的数
break;
case "sin": case "cos": case "tan": case "n!":
result = operation(text, str);
flag = 1;
break;
}
if(result != null) tv.setText(result);
}
}
结果:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341