Android学习之计算器app(java + 详细注释 + 源码)
运行结果:
基础的四则运算:
可能会出现的问题以及解决方法:
问题1:出现多个操作符。
例子:1++++++2
解决方法:
在用户点击操作符之后,去检查之前的最后一位,如果最后一位也是操作符的话,就进行替代操作。
问题2:小数点问题。
例子:0......1 以及 .2
解决方法:
对于0.....1的问题,用的是一个全局变量 addPoint,当它为true的时候才可以进行添加小数点操作。
当点击 π 或者是 小数点之后 就要把 addPoint 置为false,也即表示不能再去添加小数点了。
当点击操作符或者是C(清空)之后就要把 addPoint 置为false,也即表示可以再去添加小数点了。
问题3:非法操作。
例子:
1:除0
2:阶乘溢出
3:负数开根号
4:logx, 其中x <= 0
5:(0.123)!
6:(-3)!
解决方法:
对每个运算进行提前监控,如果出现违规操作要把用户的除了C(清空)按钮外全部禁掉,然后做出违规提示,参考Win11自带计算器。但是感觉更加规范的是 可以自定义异常 然后去对应到每一个的异常处理问题。
问题4:负数的复杂性
例子:-3 对这个实现起来还是比较麻烦的
解决方法:
对这个不进行特殊判断,还是点击 "-" 之后看看它的前面有没有数字,如果没有的话,也去补上0, 这个0是默认的。
新增括号功能:
对括号进行了显示,以及可以进行括号运算。
在界面显示出右括号和左括号的数量,而且右括号的数量数不能多于左括号的,参照win11自带计算器。
可能出现的问题以及解决方法:
问题1:出现 (+)。
也即是括号里面只有操作符。
解决的方法:
1:当点击运算符的时候,检查它的前面是不是 "(", 如果是的话就去自动去补0。
2:当点击 "(" 的时候,去检查它的前面是不是 操作符,如果是的话就去自动补0 。
问题2:出现(0)(0)这样的情况。
解决方法:
当用户点击 "(" 的时候去校验当前已经存在的字符串的最后一位,如果它不是操作符的话,就去指定去补上一个操作符,我在这里默认的是 "x"。
问题3:出现0 + (-3) + 5 这样的情况。
解决方法:
当用户点击操作符的时候,就去检测当前已经存在的最后一个字符是不是数字,如果不是数字的话,就去补上一个默认的0,但是还会出现这样的情况0 + (0 - 3) 0 + 3,它把0补到了这里了,这里再去加一个特殊的判断,如果最后一个是 ")" 就不去加上这个默认的0。但是改为之后又出现了这样的情况:0+(0)------------,解决的方法当这个最后一个字符是 "(" 的时候再去增加默认的0。
声明:
因为作者是一个考研dog,so 没有足够的时间去写这个,只能晚上10回去之后加班写,或者在其他老师课上写,因此间隔时间比较大,而且逻辑比较乱,希望大家多多包涵。
计划:
1:后期可以去增加一个 按键声音的功能,也即是你点击一个按钮之后,就会产生特定的生硬,当然声音是作者自己那美妙的声音。
2:增加登录操作,把每个人的计算的操作给记录下来,可以查看自己历史计算记录。
java代码:
package com.findyou.myapplication;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.math.BigInteger;
import java.util.Objects;
import java.util.Stack;
public class Test_jsq extends AppCompatActivity implements View.OnClickListener {
private TextView tv_result, show_kh; // 获取文本框的内容 为了进行设置
// 第一个操作数
// 第二个操作数
// 运算符
private String operator = "";
// 结果
private String result = "";
// 显示的文本内容 刚开始的时候要显示的是 0
private String showText = "0"; // 3+2
private Boolean addPoint = true;
private boolean denominatorIsZero = false; // 分母是否为0
private final String ISZERO = "分母不可为0!";
private final String FACTORIALERROR = "小数和分数没有阶乘,阶乘只在自然数中进行";
private final String OVERFLOW = "溢出";
private final String NAGATIVE_HAS_NO_FACTORIAL = "负数没有阶乘";
private final String NAGATIVE_HAS_NO_SQRT = "根号下要大于等于0";
private final String LN_NEED_GREATER_THAN_ZERO = "ln里面需要大于0";
// 新增加的 左右括号的显示操作 初始化的括号的数量都显示为 0
private int leftParenthesis = 0, rightParenthesis = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculator);
// 获取tv_result ctrl + alt + f 变为全局变量
tv_result = findViewById(R.id.tv_result);
show_kh = findViewById(R.id.show_kh); // 对括号的截取和显示
Button btn_cancel = findViewById(R.id.btn_cancel);
btn_cancel.setOnClickListener(this);
// 给每个按钮设置监听
findViewById(R.id.btn_cancel).setOnClickListener(this);
findViewById(R.id.btn_divide) .setOnClickListener(this);//“除法"按钮
findViewById(R.id.btn_multiply).setOnClickListener(this); // "乘法"按钮
findViewById(R.id.btn_clear) .setOnClickListener(this);
findViewById(R.id.btn_seven).setOnClickListener(this); // 数字7
findViewById(R.id.btn_eight).setOnClickListener(this); // 数字8
findViewById(R.id.btn_nine).setOnClickListener(this); // 数字9
findViewById(R.id.btn_plus) .setOnClickListener(this) ;
findViewById(R.id.btn_four).setOnClickListener(this); // 数字4
findViewById(R.id.btn_five).setOnClickListener(this); // 数字5
findViewById(R.id.btn_six) .setOnClickListener(this); // 数字6
findViewById(R.id.btn_minus).setOnClickListener(this);// "减法"按钮
findViewById(R.id.btn_one).setOnClickListener(this); // 数字1
findViewById(R.id.btn_two).setOnClickListener(this); // 数字2
findViewById(R.id.btn_three).setOnClickListener(this); // 数字3
findViewById(R.id.btn_reciprocal).setOnClickListener(this);// 求倒数按钮
findViewById(R.id.btn_zero).setOnClickListener(this); // 数字0
findViewById(R.id.btn_dot).setOnClickListener(this);// “小数点"按钮
findViewById(R.id.btn_equal).setOnClickListener(this);// "等号"按钮
findViewById(R.id.btn_sqrt) .setOnClickListener(this) ;// 开根号按钮
findViewById(R.id.btn_PI).setOnClickListener(this); // π按钮的监听
findViewById(R.id.btn_factorial).setOnClickListener(this); // 阶乘按钮的监听
findViewById(R.id.btn_e).setOnClickListener(this); // e 按钮的监听
findViewById(R.id.btn_abs).setOnClickListener(this); // 绝对值 按钮的监听
// 新增加的功能
findViewById(R.id.btn_left_kh).setOnClickListener(this); // 对左括号 按钮进行监听
findViewById(R.id.btn_right_kh).setOnClickListener(this); // 对右括号 按钮进行监听
findViewById(R.id.btn_log).setOnClickListener(this); // 对 log 按钮 进行监听
findViewById(R.id.btn_ln).setOnClickListener(this); // 对 ln 按钮进行监听
}
// 变为公用的
@Override
public void onClick(View v) {
// 测试 是否能正常显示在界面 很好奇 为什么这个 测试的 没有 ban 掉
// tv_result.setText(((TextView) v).getText().toString());
String inputText;
// 如果是开根号的按钮
if (v.getId() == R.id.btn_sqrt) {
inputText = "√";
} else {
inputText = ((TextView) v).getText().toString();
}
int t = v.getId();
// 点击了清空按钮
if (t == R.id.btn_clear) {
// 清空的时候 要去恢复按钮
illegal(true);
// 注意二者顺序
clear();
// 也要去清空括号
clearKh();
} else if(t == R.id.btn_cancel) { // 后退按钮
// 注意 后退 是 不能 去进行 后退 操作符号 的
showText = Backoff(showText);
if(Objects.equals(showText, "")) {
showText = "0"; // 最后一个都被清空了
}
// 刷新文本
refreshText(showText);
} else if(t == R.id.btn_plus || t == R.id.btn_minus || t == R.id.btn_multiply || t == R.id.btn_divide){ // 点击了 加 减 乘 除
// 如果操作符的前面是小数点的话 就要把小数点给省略掉 0.1 - 0. + ---> 0.1 - 0 +
addPoint = true; // 把小数点可以更新了
operator = inputText;
char temp = showText.charAt(showText.length() - 1);
// 每当进行 加减操作的时候 先去看看它的最后一个是不是有效的 不是有效的话 要去主动去增加一个 0 无论是小数点还是普通的加减
// 增加的 这一个 可能出现了问题了
// if(!checkIsNum(showText.charAt(showText.length() - 1)) && temp != '(' && temp != ')') {
// showText = showText + "0";
// }
// 这里防止出现这样的情况: (+0)的情况
// if(checkIskh(temp)) {
// showText = showText + "0";
// }
// 查看当前这个字符串的最后一个 也是操作符的话 就把它给覆盖掉
if(checkIsOp(temp)) {
// 就把当前的字符串的最后一个给替换掉
showText = showText.substring(0, showText.length() - 1) + operator;
refreshText(showText);
} else {
// 这里解决的是 0.-3 这样的问题 解决的方法是把 小数点给去掉
if(showText.charAt(showText.length() - 1) == '.') {
showText = showText.substring(0, showText.length() - 1);
}
refreshText(showText + operator);
}
// 等号 的操作
} else if(t == R.id.btn_equal) { // 等号按钮
// 进行规格化
String ret = Normalized(js(showText));
refreshText(ret);
// 等号的话 也要去恢复小数点的操作
addPoint = true;
clearKh();
// 然后去清空掉
// showText = "0";
//1 + 0123.0 √
} else if(t == R.id.btn_sqrt) { // 开根号
js3(1); // 1 表示的是开根号的操作
} else if(t == R.id.btn_reciprocal) { // 求倒数
js3(2);
} else if(t == R.id.btn_PI) { // 点击了 π 的 操作
js3(4);
} else if(t == R.id.btn_factorial) { // 点击了阶乘的操作
js3(3);
} else if(t == R.id.btn_abs) {
js3(5); // 点击了绝对值的操作
} else if(t == R.id.btn_e) { // 点击的是 e 的 操作
js3(6);
} else if(t == R.id.btn_ln) { // 点击的是 ln 的操作
js3(7);
}
else if(t == R.id.btn_left_kh) {
leftParenthesis ++ ;
// 刷新 界面的括号显示数字 并且把 括号给拼接上去
// 这里也要特判一下 可能存在 这样的情况 比如: (0)() 要把它变成 (0)x(0) 这样的情况
char pre = showText.charAt(showText.length() - 1);
if(pre == ')') {
showText += 'x';
}
// 这里需要去校验一种情况是 1( 要把它变为 1 + (这样的形式
if(checkIsNum(pre)) {
showText += "+";
}
refreshText(showText + inputText);
} else if(t == R.id.btn_right_kh) { // 点击了右括号
// 为了让他们进行匹配 也即是 存在 对应的左括号的时候才进行匹配
if(rightParenthesis < leftParenthesis) {
rightParenthesis ++ ;
// 刷新 界面的右括号显示数字 并且把括号给拼接上去
// 这里要单独去检验一下 可能是 () 这样的情况是不允许的 要去在左括号的后面去拼接一个 0
char pre = showText.charAt(showText.length() - 1);
if(pre == '(') {
showText += "0";
}
// 这里也要去防止 (0+)这样的情况
if(checkIsOp(pre)) {
showText += "0"; // 去给它去补上 0
}
refreshText(showText + inputText);
}
}
else {// 点击了 数字 和 小数点
// 这里要去监控 如果之前点击了小数点 这里的话 就不能再去进行拼接了
if(inputText.equals(".")) {
// 这里可能会出现很多的 小数点 例如: 0.000.
if(!addPoint) { // 表示不可以去添加小数点
refreshText(showText); // 保持原来的
return ;
} else {
// 这里要去判断一下 小数点的前方是否为操作符 如果是的话 就自动拼接一个 0
char pre = showText.charAt(showText.length() - 1);
if(checkIsOp(pre) || checkIskh(pre)) {
showText = showText + "0";
}
refreshText(showText + inputText); // 保持原来的
addPoint = false;
return;
}
}
char pre = showText.charAt(showText.length() - 1);
// 如果前面不是数字的话 要去自动补上加号
if(pre == ')') {
showText += "+";
}
refreshText(showText + inputText); // 拼接
}
}
/**
* 计算的是 开根号 倒数 阶乘 π e
* @param num 约定好的标志
* 1:开根号
* 2:倒数
* 3:阶乘
* 4:π
* 5:绝对值
* 6:e
* 7:ln
*/
private void js3(int num) {
String snum = getLastNumber(showText);
String newNumber = "";
if(num == 1) { // 开根号
if(Double.parseDouble(snum) < 0) {
abnormal(NAGATIVE_HAS_NO_SQRT);
return;
}
newNumber = String.valueOf(Math.sqrt(Double.parseDouble(snum)));
} else if(num == 2) { // 倒数的操作
// 先去检查分母是不是为0的
if(Double.parseDouble(snum) - 0.0 == 0) {
abnormal(ISZERO); // 分母不可为 0
return ;
}
// 开始逻辑上的计算
newNumber = String.valueOf(1.0 / Double.parseDouble(snum));
} else if(num == 3) { // 阶乘
// 注意:小数和分数没有阶乘 阶乘法只在自然数中进行
if(!addPoint || showText.contains(".")) {
// 表示当前是增加了小数的 是不能去进行阶乘的运算的
abnormal(FACTORIALERROR);
return; // 这个return 是为了防止 其他信息 的覆盖
} else { // 表示当前是没有小数的 是可以进行阶乘的
if(Integer.parseInt(snum) > 100) {
abnormal(OVERFLOW); // 阶乘太大会导致溢出
return ;
} else if(Integer.parseInt(snum) < 0 ) {
abnormal(NAGATIVE_HAS_NO_FACTORIAL); // 负数没有阶乘
return;
}
newNumber = factorial(Integer.parseInt(snum));
}
} else if(num == 4) { //π
addPoint = false; // 注意 点击了PI 之后也要去限制小数点的
newNumber = String.valueOf(Math.PI);
} else if(num == 5) { // 绝对值的操作
// 感觉这个绝对值 有点鸡肋
if(Double.parseDouble(snum) < 0 ) {
newNumber = snum.substring(1); // 把前面的符号给截取掉
} else {
// 但是这个新的 还要去规范一下 不能把前置 0 给显示
newNumber = cancelZero(snum); // 不进行截取
}
} else if(num == 6) { // e 2.71828
newNumber = String.valueOf(Math.E);
} else if(num == 7) { // ln 的操作
if(Double.parseDouble(snum) <= 0) {
abnormal(LN_NEED_GREATER_THAN_ZERO);
return ;
}
newNumber = String.valueOf(Math.log(Double.parseDouble(snum)));
}
// 我需要找到最后这个的位置
// over: 获得这个的num的位置 然后进行替换 把老的替换为新的
// 我需要去找到 最后一个操作符的位置
int pos = getLastOperatorPose(showText);
// 开始进行替代 注意的是 这里的 substring 第二个参数表示的最后的位置 注意是 前闭后开的
showText = showText.substring(0, pos + 1);
// 再去拼接新的
showText = showText + newNumber;
// 然后再去在界面进行显示出来
refreshText(showText);
}
/**
* 清空括号 也即是下面这种情况
* 1: 按下C的时候
* 2: 等号的时候
*/
private void clearKh() {
leftParenthesis = 0;
rightParenthesis = 0;
// 清空之后要去刷新 数量
refreshText(showText);
}
/**
* 对结果进行规格化
* @param text 传过来 需要规格化的数据
* 例如: 00001 那么要返回的就是 1
* @return
*/
private String cancelZero(String text) { // 取消前置无效0 以及后置无效0
int j = 0;
// 要对 test 进行校验一个
// 有哪些情况呢?
// 1: 00008
// 2: 0000.1
for(int i = 0; i < text.length() - 1; i ++ ) {
if(text.charAt(i) == '0' && (!checkIsOp(text.charAt(i + 1)) && text.charAt(i + 1) != '.' || text.charAt(i + 1) == ')' || text.charAt(i + 1) == '(')) {
j = i + 1;
} else {
break;
}
}
text = text.substring(j); // 从这里开始截取 并包括当前这个
return text;
}
/**
* 获取 num 的 阶乘的
* @param num 想要获取的 阶乘的 num
* @return
*/
private String factorial(int num) {
// 为了解决阶乘太大 用的是 BigInteger
BigInteger result = BigInteger.ONE; // 初始化为 1
for (int i = 1; i <= num; i++) {
result = result.multiply(BigInteger.valueOf(i)); // 逐步相乘
}
return String.valueOf(result); // 最后再去转换为 string类型的 给进行输出显示
}
/**
* 根据text 抛出指定的异常
*/
private void abnormal(String show) {
// 要去禁用按钮
illegal(false);
tv_result.setText(show);; // 并把错误的信息给显示到文本框里面
}
/**
* 后退按钮的操作
* @param t 出来的逻辑字符串
* @return 返回的是 后退的字符串
*/
private String Backoff(String t) {
for(int i = t.length() - 1; i >= 0; i -- ) {
if(checkIsNum(t.charAt(i))) {
// 需要注意的是 如果退的是 小数点的话 要求进行恢复
if(t.charAt(i) == '.') {
// 恢复 可以增加 小数点 的操作
addPoint = true;
}
// 我就去后退一位
return t.substring(0, i);
} else {
// 否则的话 就直接去回去的
break;
}
}
return t;
}
/**
* 获得最后一个操作符的位置
* @param showText 传来的字符串
* @return 返回的是 最后一个操作符的位置
* 例如: 1+2 返回的是1
*/
private int getLastOperatorPose(String showText) {
int pos = -1;
if(showText.charAt(0) == '-') {
return pos;
}
for(int i = showText.length() - 1; i >= 0; i -- ) {
if(checkIsOp(showText.charAt(i)) || checkIskh(showText.charAt(i))) { // 如果检查发现是 操作符的话 就去返回它的下标 是包括它的
return i;
}
}
// 这个表示的是没有操作符的
return pos;
}
/**
* 输出结果的规格化
* @param js
* @return 返回的是 规格化之后的结果
*/
private String Normalized(double js) {
// 是可以去进行规格化的
if(js - (int)(js) == 0) {
return String.valueOf((int)(js));
} else {
return String.valueOf(js);
}
}
/**
* 清空 并进行 初始化
* 新增 对 小数点 的恢复
*/
private void clear() {
// 清空的时候 注意把 小数点的功能也给进行恢复
addPoint = true;
refreshOperate("");
refreshText("0"); // 0即表示为不存在 其实也是存在
}
// 刷新运算结果
private void refreshOperate(String new_result) {
result = new_result;
operator = "";
}
/*
* 刷新 文本 的操作
* 再去加上 输出的校验
* */
private void refreshText(String text) {
String khNum = "左括号的数量: " + leftParenthesis + " 右括号的数量: " + rightParenthesis;
// 这里在刷新的时候 也要把 括号的数量给显示出来
show_kh.setText(khNum);
// 在刷新之前 对结果进行规格化一下 去除前置0的 那些没有效的数据 但是要对小数进行特判
text = cancelZero(text);
showText = text; // 默认一直在拼接
if(denominatorIsZero) { // 分母是否为0
showText = ISZERO;
}
tv_result.setText(showText);
// 对 等号 按钮的监控
if(leftParenthesis == rightParenthesis) {
findViewById(R.id.btn_equal).setEnabled(true);
} else {
findViewById(R.id.btn_equal).setEnabled(false);
}
}
/**
* 主要的计算功能
* @param s 传过来的 字符串 要去计算的字符串 这里面没有等号
* @return
*/
private double js(String s) {
// 第一个的 负数 是比较特殊的 要进行特判
// 前面直接加上一个 0
s = "0" + s;
// 这里需要做一个判断
// 可能是-3 这样的 但是返回的 也是-3 不要在进行计算下去了 这是一个独特的
// if(s.charAt(0) == '-') {
// s = "0" + s;
// } else if(Objects.equals(operator, "")) {
// return Double.parseDouble(s);
// }
// 用到java里面的桟的算法
// 存取的是 数字
Stack<Double> number = new Stack<>();
// 存取的是 操作符
Stack<Character> op = new Stack<>();
String t = "";
for(int i = 0; i < s.length(); i ++ ) {
char temp = s.charAt(i);
// 如果当前这个 temp 是 运算符的话
if(checkIsOp(temp) || temp == '(' || temp == ')') { // 如果当前这个是 运算符
// 这样的话 就需要把 字符串给转换为 Double
// 注意 放进去的前提是不为空的 把他放到 桟里面
if(!t.isEmpty()) {
number.push(Double.valueOf(t));
}
t = "";
// 然后 看看 当前的字符是什么类型的
if(temp == '+' || temp == '-') {
while(!op.isEmpty()) {
// 拿到桟顶元素
char operator = op.peek();
if(operator == '(') { // 左括号的优先级是 最低 的
break;
}
op.pop();
// 然后再从 整数桟里面 去拿出来两个数 让其进行计算
// TODO: 这两步数 是容易造成 error的 这点需要去着重的去关注
double t1 = number.peek();
number.pop();
double t2 = number.peek();
number.pop();
// 注意的是 后 操作 前 的
double ret = js2(t2, t1, operator);
number.push(ret);
}
// 到这里的时候 就表示 op里面是空的了
op.push(temp);
} else if(temp == 'x' || temp == '÷') {
// 当时 乘法或者是 除法的时候 要去校验 它的下面是不是比它低的
// 或者可以写成 前提是不为空 然后 op.peek() == 'x' || op.peek() == '➗'
while(!op.isEmpty() && op.peek() != '+' && op.peek() != '-' && op.peek() != '(') {
// 拿到桟顶元素
char operator = op.peek();
op.pop();
// 然后再从 整数桟里面 去拿出来两个数 让其进行计算
// TODO: 这两步数 是容易造成 error的 这点需要去着重的去关注
double t1 = number.peek();
number.pop();
double t2 = number.peek();
number.pop();
double ret = js2(t2, t1, temp);
number.push(ret);
}
// 到这里的时候 是可以去当进去的
op.push(temp);
} else if(temp == ')') { // 这里对右括号单独进行限制
// 只要还没遇到 左括号 就一直去把里面运算符的给弹出来 而且弹出来的时候 也把数字给弹出来两个 然后和这个弹出来的运算符进行计算
while(!op.isEmpty()) {
char operator = op.peek();
op.pop();
if(operator == '(') {
break; // 就匹配成功了
}
// 否则的话 就取出来两个数字 然后把这个操作符 让这两个数进行运算的结果 放到存取数的桟里面
// TODO: 但是这个的前提是存在的
double t1 = number.peek();
number.pop();
double t2 = number.peek();
number.pop();
double ret = js2(t2, t1, operator);
number.push(ret);
}
} else if(temp == '(') { // 左括号的话 直接 push 进去
op.push(temp);
}
} else if(checkIsNum(temp)){ // 说明是 数字 或者是小数点
t = t + temp;
}
}
// Debug 了半天才发现是这里出现了问题 我也是服了
if(!t.isEmpty()) {
// 注意在 类型转换的时候 看看是不是为空的 因为空的话 是不能去进行转换的
number.push(Double.valueOf(t));
}
// 开始计算
while (number.size() > 1) {
// 这里 没有运算符 也是很致命的
if(op.isEmpty()) {
break;
}
double t1 = number.peek();
number.pop();
double t2 = number.peek();
number.pop();
number.push(js2(t2, t1, op.peek()));
op.pop();
}
operator = "";
return number.peek();
}
/**
* 计算 + - * / 的
* @param t1
* @param t2
* @param temp
* @return
*/
private double js2(double t1, double t2, char temp) {
if(temp == '+') {
return t1 + t2;
}
if(temp == '-') {
return t1 - t2;
}
if(temp == 'x') {
return t1 * t2;
}
if(temp == '÷') {
// 出现了 分母为0
if(t2 == 0 ) {
abnormal(ISZERO); // 分母不可为0 && 限制按钮的点击
}
return t1 / t2;
}
return 0.0; // 这个是假的
}
/**
* 检查 是不是操作符
* @param t
* @return
*/
private Boolean checkIsOp(Character t) {
return t == '+' || t == '-' || t == '÷' || t == 'x';
}
/**
* 检查是不是 数字 这里把小数点也认为是数字了
* @param t
* @return
*/
private Boolean checkIsNum(Character t) {
return (t >= '0' && t <= '9') || t == '.';
}
/**
* 获得字符串 最后 一个 数字
* @param s
* @return
*/
private String getLastNumber(String s) {
String ret = "";
if(s.charAt(0) == '-') { // 表示的是负数
ret = s;
} else {
for(int i = s.length() - 1; i >= 0; i -- ) {
if(checkIsNum(s.charAt(i))) {
ret = s.charAt(i) + ret;
} else {
break;
}
}
ret = "0" + ret;
}
// 这个去解决的是 1233 + 也即是最后一个不是数字
if(ret.contains(".")) { // 这个的目的是为了 防止 出现小数点之后 没有出现数字的情况 比如: 123.
ret = ret + "0";
}
return ret;
}
/**
* 去检查这个 t 是不是括号 因为要为括号进行特殊的操作
* @param t
* @return
*/
private boolean checkIskh(char t) {
return t == '(' || t == ')';
}
// 封掉所有的按钮 单独剩下一个 清空的按钮 要去做出适当的提示
// 表示的是 不合法 把全部的按钮全都给禁用了 除了 C
private void illegal(boolean value) {
denominatorIsZero = !value;
findViewById(R.id.btn_cancel).setEnabled(value);
findViewById(R.id.btn_divide).setEnabled(value);
findViewById(R.id.btn_multiply).setEnabled(value);
findViewById(R.id.btn_clear).setEnabled(true); // 这个是特殊的
findViewById(R.id.btn_seven).setEnabled(value);
findViewById(R.id.btn_eight).setEnabled(value);
findViewById(R.id.btn_nine).setEnabled(value);
findViewById(R.id.btn_plus).setEnabled(value);
findViewById(R.id.btn_four).setEnabled(value);
findViewById(R.id.btn_five).setEnabled(value);
findViewById(R.id.btn_six).setEnabled(value);
findViewById(R.id.btn_minus).setEnabled(value);
findViewById(R.id.btn_one).setEnabled(value);
findViewById(R.id.btn_two).setEnabled(value);
findViewById(R.id.btn_three).setEnabled(value);
findViewById(R.id.btn_reciprocal).setEnabled(value);
findViewById(R.id.btn_zero).setEnabled(value);
findViewById(R.id.btn_dot).setEnabled(value);
findViewById(R.id.btn_equal).setEnabled(value);
findViewById(R.id.btn_sqrt).setEnabled(value);
// 新增的 限制按钮
findViewById(R.id.btn_PI).setEnabled(value);
findViewById(R.id.btn_factorial).setEnabled(value);
findViewById(R.id.btn_e).setEnabled(value);
findViewById(R.id.btn_abs).setEnabled(value);
// 新增的 限制按钮
findViewById(R.id.btn_log).setEnabled(value);
findViewById(R.id.btn_ln).setEnabled(value);
findViewById(R.id.btn_left_kh).setEnabled(value);
findViewById(R.id.btn_right_kh).setEnabled(value); // 对右括号 按钮进行监听
}
}
xml(界面)代码:
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#EEEEEE"
android:padding="5dp"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--显示简单 计算器 字样-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/simple_calculator"
android:gravity="center"
android:textColor="@color/black"
android:textSize="20sp"/>
<TextView
android:id="@+id/show_kh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="左括号数量为: 0 右括号数量为: 0"
android:gravity="center"
android:textColor="@color/black"
android:textSize="20sp"/>
<!-- 计算机 文本的显示-->
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:text="0"
android:textColor="@color/black"
android:lines="3"
android:gravity="right|bottom"
android:textSize="25sp"/>
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="4"
android:rowCount="7">
<!--后退一个-->
<Button
android:id="@+id/btn_cancel"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/cancel"
android:textColor="@color/black"
/>
<!--除法-->
<Button
android:id="@+id/btn_divide"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/divide"
android:textColor="@color/black"
/>
<!--乘法-->
<Button
android:id="@+id/btn_multiply"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/multiply"
android:textColor="@color/black"
/>
<!--清零操作-->
<Button
android:id="@+id/btn_clear"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/clear"
android:textColor="@color/black"
/>
<!--新增的操作-->
<Button
android:id="@+id/btn_PI"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/PI"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_e"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/e"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_abs"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/abs"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_factorial"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/factorial"
android:textColor="@color/black"
/>
<!--这里又是新增加的 比如 左括号 右括号 -->
<Button
android:id="@+id/btn_log"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/log"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_ln"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="ln"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_left_kh"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/left_kh"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_right_kh"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/right_kh"
android:textColor="@color/black"
/>
<!--下面是第二行-->
<Button
android:id="@+id/btn_seven"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/seven"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_eight"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/eight"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_nine"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/nine"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_plus"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/plus"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_four"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/four"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_five"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/five"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_six"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/six"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_minus"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/minus"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_one"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/one"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_two"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/two"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_three"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/three"
android:textColor="@color/black"
/>
<!--这里显示的根号的图片-->
<Button
android:id="@+id/btn_sqrt"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/sqrt"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_reciprocal"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/reciprocal"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_zero"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/zero"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_dot"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/dot"
android:textColor="@color/black"
/>
<Button
android:id="@+id/btn_equal"
android:layout_width="0dp"
android:layout_height="@dimen/button_height"
android:textSize="@dimen/button_font_size"
android:layout_columnWeight="1"
android:gravity="center"
android:text="@string/equal"
android:textColor="@color/black"
/>
</GridLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
strings.xml里面的代码:
<resources>
<string name="app_name">黄淮计算器</string>
<string name="action_settings">Settings</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="next">Next</string>
<string name="previous">Previous</string>
<string name="hello_word">hello_word</string>
<string name="text_for_color">textForColor</string>
<string name="lorem_ipsum">
</string>
<string name="findyou">FindYou</string>
<string name="this_is_findyou">This is FindYou</string>
<string name="this_is_activity_main_2">除了奋斗 别无选择</string>
<!--计算器的定义-->
<string name="simple_calculator">黄淮计算器</string>
<string name="cancel">⌫</string>
<string name="divide">÷</string>
<string name="multiply">x</string>
<string name="clear">C</string>
<string name="seven">7</string>
<string name="eight">8</string>
<string name="nine">9</string>
<string name="plus">+</string>
<string name="four">4</string>
<string name="five">5</string>
<string name="six">6</string>
<string name="minus">-</string>
<string name="one">1</string>
<string name="two">2</string>
<string name="three">3</string>
<string name="reciprocal">1/x</string>
<string name="zero">0</string>
<string name="dot">.</string>
<string name="sqrt">√</string>
<string name="equal">=</string>
<string name="check_sex">请选择你的性别</string>
<string name="PI">π</string>
<string name="e">e</string>
<string name="abs">|x|</string>
<string name="factorial">n!</string>
<string name="log">log</string>
<string name="left_kh">(</string>
<string name="right_kh">)</string>
</resources>
如果这对你有帮助的话,记得start一下哦,你的star对我很重要!!!
gitee地址:
FindYou/移动开发