安卓计算器:
实现功能:
(1)能实现基本的加减乘除运算、回退和清空输入。
(2)竖屏时能实现基本的加减乘除运算、回退和清空输入。横屏时变为科学计算器,实现函数计算、进制换算等功能。
(3)数字按键依照电话拨号键盘顺序排列。
(4)点击菜单可对计算器相关特性进行配置。
(5)输入计算公式,按等号键输出计算结果。
(6)公式输入和结果显示区应支持长按弹出复制、粘贴功能。
(7)使用计算器过程中应不弹出软键盘。
(8)可以通过进度条实时调整计算结果保留的小数点后位数,或者通过音量键完成同样的效果。
(9)实现附加功能:三角函数、阶乘、XY、√(Y&X)及括号,如sin(90)。
(10)输入表达式按优先级计算,按等号输出结果。
(11)对常用键布局需考虑特殊处理。
(12)处理精度和容错问题:
a.1/3+1/3+1/3;
2.1+0.001;
1.1-1.001;
1/0、1/(1-1)和1/sin(0)等;
3/2;
对有附加功能的需要处理特殊值,如:√(2&-1) 等。
竖屏时
public class MainActivity extends AppCompatActivity {
String formula = "";//公式方程
Boolean zeroMark = true; //允许输入一个0
Boolean zeroCon = false;//允许持续输入0
Boolean docMark = true;// . 可以输入 .
Boolean resultMark = false; //结果是否计算出
Boolean transformMark = false; //是否进行二进制转化
Boolean errorMark = false;
Boolean numAndOpMark = true;
int color = 0xffffffff;
private static final String REGEX = "^\\d+$";//all is num
int precision = 3; //保留小数点位数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); //屏幕旋转
setContentView(R.layout.col);
EditText show = findViewById(R.id.show);
show.setText("");
show.setSelectAllOnFocus(true); // 设置长按时选择全部
calculator();
}
public void calculator() {
disableShowInput(); // 不让弹出软键盘
EditText show = findViewById(R.id.show);
Button dot = findViewById(R.id.dot);
Button zero = findViewById(R.id.zero);
Button one = findViewById(R.id.one);
Button two = findViewById(R.id.two);
Button three = findViewById(R.id.three);
Button four = findViewById(R.id.four);
Button five = findViewById(R.id.five);
Button six = findViewById(R.id.six);
Button seven = findViewById(R.id.seven);
Button eight = findViewById(R.id.eight);
Button nine = findViewById(R.id.nine);
Button add = findViewById(R.id.add);
Button sub = findViewById(R.id.sub);
Button division = findViewById(R.id.division);
Button back = findViewById(R.id.back);
Button AC = findViewById(R.id.AC);
Button mul = findViewById(R.id.mul);
Button eval = findViewById(R.id.eval);
Button percent = findViewById(R.id.percent);
Button sin = findViewById(R.id.sin);
Button power = findViewById(R.id.power);
Button factorial = findViewById(R.id.factorial); //阶乘
Button square = findViewById(R.id.square); //开根号
Button brackets = findViewById(R.id.brackets);
Button transform = findViewById(R.id.transform);
dot.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum(".");
}
});
zero.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("0");
}
});
one.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("1");
}
});
two.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("2");
}
});
three.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("3");
}
});
four.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("4");
}
});
five.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("5");
}
});
six.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("6");
}
});
seven.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("7");
}
});
eight.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("8");
}
});
nine.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doNum("9");
}
});
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doOp("+");
}
});
sub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doOp("-");
}
});
mul.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doOp("×");
}
});
division.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doOp("÷");
}
});
AC.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
reSetStatus();
show.setText("");
}
});
back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (formula.length() > 0) {
if (!formula.contains("(D->B)")) {
if (lastStr().equals(".")) {
docMark = true;
}
formula = formula.substring(0, formula.length() - 1);
} else {
formula = formula.replace("(D->B)", "");
numAndOpMark = true;
transformMark = false;
}
show.setText(formula);
show.setTextColor(0xff000000);
}
}
});
eval.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String result = "";
if (transformMark) { // 先判断是不是要进行二进制转化
doTransform();
return;
}
delLastOp(); // 如果式子是 4- 进行计算,我们打算将-号去掉,结果为4
try {
result = Result.getRes(formula) + ""; //将计算式放入getRes函数中进行计算
} catch (Exception e) {
show.setText(e.getMessage()); //getRes中抛出的异常进行抓取并显示
show.setTextColor(0xffff0000);
errorMark = true;
return;
}
System.out.println(result + "result");
if (result.contains("E") && !result.contains("E-")) {// 结果使用了科学计数法表示,我们要根据情况进行处理
show.setText(result);
Toast toast = Toast.makeText(getApplicationContext(), "数值太大,已用科学计数法表示", Toast.LENGTH_SHORT);
toast.show();
return;
}
// String intPart;
// if (result.length() > 12) {
if (result.contains("E-")) {
BigDecimal decimal = new BigDecimal(result);
result = decimal.toPlainString();
}
if (result.length() > 12)
{
result = result.substring(0, 11);
}
result = doPrecision(result); //进行精读修改
show.setText(result);
reSetStatus();
formula = result;
resultMark = true;
docMark = true;
} catch (Exception e) {
e.printStackTrace();
}
}
});
percent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (formula.length() > 0) {
if (!numAndOpMark) {
return;
}
formula = "(" + formula + ")*0.01";
try {
show.setText(doEval(formula));
formula = doEval(formula);
} catch (Exception e) {
show.setText(e.getMessage());
}
}
}
});
sin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!numAndOpMark) {
return;
}
formula = formula + "sin(";
show.setText(formula);
}
});
square.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!numAndOpMark) {
return;
}
formula = formula + "v(";
show.setText(formula);
}
});
power.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!numAndOpMark) {
return;
}
formula = formula + "^";
show.setText(formula);
}
});
factorial.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!numAndOpMark) {
return;
}
try {
if (formula.contains(".") )
{
Toast toast = Toast.makeText(getApplicationContext(), "小数不可以阶乘", Toast.LENGTH_SHORT);
toast.show();
return;
}
if (Result.getRes(formula) < 171) {
formula = formula + "!";
show.setText(formula);
} else {
Toast toast = Toast.makeText(getApplicationContext(), "数值太大!", Toast.LENGTH_SHORT);
toast.show();
show.setTextColor(0xffff0000);
resultMark = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
brackets.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!numAndOpMark) {
return;
}
if (lastIsNum() || lastStr().equals(")")) {
formula = formula + ")";
} else {
formula = formula + "(";
}
show.setText(formula);
}
});
transform.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (formula.matches(REGEX)) {
formula = formula + "(D->B)";
show.setText(formula);
transformMark = true;
numAndOpMark = false;
}
}
});
}
public String doPrecision(String result) {
System.out.println(result + "rep");
String tail = result.split("\\.")[1];
String pre = result.split("\\.")[0];
int deltaPre = precision - tail.length();
if (deltaPre > 0) {
for (int i = 0; i < deltaPre; i++) {
result = result + "0";
}
} else if (deltaPre < 0) {
double doubleResult = Double.parseDouble(result);
BigDecimal bigResult = new BigDecimal(doubleResult);
result = bigResult.setScale(precision, BigDecimal.ROUND_HALF_UP).toString();
}
System.out.println(result + "pre");
return result;
}
public void reSetStatus() { //将各个监控状态设为初始状态
EditText show = findViewById(R.id.show);
show.setTextColor(0xff000000);
formula = "";
zeroMark = true;
zeroCon = false;
docMark = true;
resultMark = false;
transformMark = false;
numAndOpMark = true;
}
@SuppressLint("SetTextI18n")
public void doTransform() { //二进制转化方法
EditText show = findViewById(R.id.show);
transformMark = false;
String num = formula.split("\\(")[0];
show.setText(Integer.toBinaryString(Integer.parseInt(num)) + "B");
resultMark = true;
docMark = true;
}
public String lastStr() {
if (formula.length() > 0) {
return formula.charAt(formula.length() - 1) + "";
} else {
return "";
}
} //返回字符的最后一个字符
public String doEval(String formula) throws Exception { //做简单的计算方法
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine se = manager.getEngineByName("js");
return se.eval(formula) + "";
}
public Boolean lastIsNum() { //最后一位是不是数字
if (formula.length() == 0) {
return false;
} else {
char lastChar = formula.charAt(formula.length() - 1);
return lastChar > 47 && lastChar < 58;
}
}
public Boolean lastIsOp() { //最后一位字符是不是操作符
return isOp(lastStr());
}
public Boolean isOp(String str) { //传递的参数是不是操作符
return (str.equals("+") || str.equals("×")
|| str.equals("÷") || str.equals("-"));
}
public void doNum(String num) {
EditText show = findViewById(R.id.show);
show.setTextColor(0xff000000);
int length = formula.length();
if (!numAndOpMark) { //当使用(D->B)后我们不再允许进行任何符号的输入
return;
}
if (errorMark) { //是否出错
reSetStatus();
errorMark = false;
}
if (resultMark) { //结果是否已算出
formula = "";
resultMark = false;
}
if (num.equals(".")) { //输的字符是不是点 .000000000000
if (docMark) { // && !isOp(lastStr())
formula = formula + '.';
show.setText(formula);
docMark = false;
zeroCon = true;
}
return;
}
if (num.equals("0")) { //是不是0? 00000000000
if (zeroCon || zeroMark) {
formula = formula + '0';
}
show.setText(formula);
zeroMark = false;
return;
}
if (formula.startsWith("0") && length == 1) { //0的特殊情况 09 -> 9
formula = "";
}
if (length > 2 && formula.endsWith("0") && isOp(formula.charAt(length - 2) + "")) {
formula = formula.substring(0, length - 1); // 0的特殊情况 23 + 09 -> 23 + 9
}
formula = formula + num; //加入计算式
zeroCon = true;
show.setText(formula);
}
public void doOp(String op) {
EditText show = findViewById(R.id.show);
show.setTextColor(0xff000000);
if (!numAndOpMark || lastStr().equals(".")) {
return;
}
if (errorMark) { //是否有错误 - is ok
reSetStatus();
errorMark = false;
}
if (resultMark) { //结果是否计算出
formula = show.getText().toString();
resultMark = false;
}
if ((lastStr().equals("÷") || lastStr().equals("×")) && op.equals("-")) {
addOp(op);
return;
}
if (formula.contains("×-") || formula.contains("÷-")) {
formula = formula.substring(0, formula.length() - 2);
}
if (formula.length() == 1 && lastStr().equals("-")) { // 只有一个减号,不允许输任何操作符
return;
}
if (formula.length() == 0 || lastStr().equals("(")) { //1+(?=-
if (op.equals("-")) { // 第一个输入的字符是不是-
addOp(op);
}
return;
}
if (lastIsOp() && formula.length() > 0) { //若最后一个字符已经时操作符,那要替换掉旧的替换符
formula = formula.substring(0, formula.length() - 1);
}
addOp(op); //如果没有以上特殊情况,则加到计算式里
}
public void addOp(String op) { // 输入操作符时大部分的重复工作进行封装
EditText show = findViewById(R.id.show);
formula = formula + op;
docMark = true;
zeroMark = true;
zeroCon = false;
show.setText(formula);
}
//==================================================================================
@SuppressLint("SetTextI18n")
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) { //设置精度(通过音量键)
TextView info = findViewById(R.id.info);
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (precision > 1) {
precision--;
info.setText("保留" + precision + "位");
Toast.makeText(this, "保留" + precision + "位", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "至少保留1位", Toast.LENGTH_SHORT).show();
}
break;
case KeyEvent.KEYCODE_VOLUME_UP:
if (precision < 10) {
precision++;
Toast.makeText(this, "保留" + precision + "位", Toast.LENGTH_SHORT).show();
info.setText("保留" + precision + "位");
} else {
Toast.makeText(this, "至多保留10位", Toast.LENGTH_SHORT).show();
}
break;
}
return super.onKeyDown(keyCode, event);
}
@SuppressLint("SetTextI18n")
@Override
public void onConfigurationChanged(Configuration newConfig) { //横竖屏切换时进行设置
@SuppressLint("CutPasteId") EditText show1 = findViewById(R.id.show);
color = show1.getCurrentTextColor();
formula = show1.getText().toString(); //如果你是复制进去的式子,那必须先从show中得到式子
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
//启动时默认是竖屏
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.col);
@SuppressLint("CutPasteId") EditText show = findViewById(R.id.show);
show.setText(formula);
show.setTextColor(color);
calculator();
}
//切换就是横屏
else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.row);
@SuppressLint("CutPasteId") EditText show = findViewById(R.id.show);
TextView info = findViewById(R.id.info);
info.setText("保留" + precision + "位");
show.setText(formula);
show.setTextColor(color);
calculator();
}
}
//========================================================================================
@Override
public boolean onCreateOptionsMenu(Menu menu) { //生成菜单项
MenuInflater inflater = new MenuInflater(this);
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@SuppressLint("NonConstantResourceId")
@Override //菜单项无所谓
public boolean onOptionsItemSelected(MenuItem item) {
EditText show = findViewById(R.id.show);
//先判断点击的是哪个id
switch (item.getItemId()) {
case R.id.font_10:
show.setTextSize(10 * 2);
break;
case R.id.font_12:
show.setTextSize(12 * 2);
break;
case R.id.font_14:
show.setTextSize(14 * 2);
break;
case R.id.font_16:
show.setTextSize(16 * 2);
break;
case R.id.font_18:
show.setTextSize(18 * 2);
break;
case R.id.blue:
show.setTextColor(Color.BLUE);
break;
case R.id.red:
show.setTextColor(Color.RED);
break;
case R.id.green:
show.setTextColor(Color.GREEN);
break;
}
return super.onOptionsItemSelected(item);
}
//======================================================================================
public void disableShowInput() { //设置键盘不可见
EditText show = findViewById(R.id.show);
Class cls = EditText.class;
Method method;
try {
method = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
method.setAccessible(true);
method.invoke(show, false);
} catch (Exception e) {//TODO: handle exception
}
try {
method = cls.getMethod("setSoftInputShownOnFocus", boolean.class);
method.setAccessible(true);
method.invoke(show, false);
} catch (Exception e) {//TODO: handle exception
}
}
//=============================================================================
public void delLastOp() { //写个小递归,后来想想好像用不到,但懒得改了
if (isOp(formula.charAt(formula.length() - 1) + "") || lastStr().equals(".")) {
formula = formula.substring(0, formula.length() - 1);
delLastOp();
}
}
ArrayStack.java
class ArrayStack {
private int maxSize; // 栈的大小
private double[] stack; // 数组,数组模拟栈,数据就放在该数组
private int top = -1;// top表示栈顶,初始化为-1
//构造器
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new double[this.maxSize];
}
//增加一个方法,可以返回当前栈顶的值, 但是不是真正的pop
public double peek() {
return stack[top];
}
//栈满
public boolean isFull() {
return top == maxSize - 1;
}
//栈空
public boolean isEmpty() {
return top == -1;
}
//入栈-push
public void push(double value) {
//先判断栈是否满
if (isFull()) {
System.out.println("表达式错误");
return;
}
top++;
stack[top] = value;
}
//出栈-pop, 将栈顶的数据返回
public double pop() {
//先判断栈是否空
if (isEmpty()) {
//抛出异常
throw new RuntimeException("表达式错误");
}
double value = stack[top];
top--;
return value;
}
//显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
public void list() {
if (isEmpty()) {
System.out.println("表达式错误");
return;
}
//需要从栈顶开始显示数据
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%d]=%d\n", i, stack[i]);
}
}
//返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示
//数字越大,则优先级就越高.
public int priority(int oper) {
if (oper == '*' || oper == '/') {
return 1;
} else if (oper == '+' || oper == '-') {
return 0;
} else if (oper == '^'||oper == '#') {
return 2;
} else if (oper == '!' || oper == 'v' || oper == '%') {
return 3;
} else if (oper == 's' || oper == 't' || oper == 'c') {
return 4;
} else {
return -1; // 假定目前的表达式只有 +, - , * , /
}
}
//判断是不是一个运算符
public boolean isNum(char val) {
return '0' <= val && val <= '9';
}
//判断是不是一个运算符
public boolean isOper(char val) {
return val == '+' || val == '-' || val == '*' || val == '/' || val == '#' || val == '^' || val == '%' || val == 's' || val == 'c' || val == 't' || val == '!' || val == 'v';
}
//判断是不是 (
public boolean isLeftBrackets(char val) {
return val == '(';
}
//判断是不是 )
public boolean isRightBrackets(char val) {
return val == ')';
}
//判断是不是 .
public boolean isPoint(char val) {
return val == '.';
}
//判断是不是 (
public boolean isTrigonometric(char val) {
return val == 's';
}
//计算方法
public double cal(double num1, double num2, int oper) {
double res = 0; // res 用于存放计算的结果
switch (oper) {
case '+':
res = num1 + num2;
break;
case '-':
res = sub(num2,num1);// 注意顺序
break;
case '*':
res = num1 * num2;
break;
case '/':
if (num1 == 0) {
throw new RuntimeException("定义域错误");
}
res = num2 / num1;
break;
case '^':
res = Math.pow(num2, num1);
break;
default:
break;
}
return res;
}
/**
* 三角函数运算、阶乘运算或者是开根操作
*
* @param num1
* @param oper
* @return
*/
public double mixedOperation(double num1, int oper) {
double res = 1; // res 用于存放计算的结果
switch (oper) {
case 's':
res = Math.sin(num1 * Math.PI / 180);
break;
case 'c':
res = Math.cos(num1 * Math.PI / 180);
break;
case 't':
res = Math.tan(num1 * Math.PI / 180);
break;
case '!':
for (int i = 1; i <= num1; i++) {
res *= i;
}
break;
case 'v':
if (num1 < 0) {
throw new RuntimeException("定义域错误");
}
res = Math.sqrt(num1);
break;
case '%':
res = num1 / 100;
break;
case '#':
res = -num1;
break;
default:
break;
}
return res;
}
double sub(double x, double y) {
BigDecimal initResult = new BigDecimal(x - y); //计算初步结果
String temp = initResult.toString();
if (temp.contains("."))
{
temp = temp + "00000000000000000000";
}else {
temp = temp + ".00000000000000000000";
}
int lengthOfInt = getLengthOfInt(x, y); //结果整形位数
int lengthOfDec = Math.max(getLengthOfDecimal(x), getLengthOfDecimal(y));
int count = lengthOfInt + lengthOfDec + 2; //最后输出的位数 = 整形位数+小数位数+小数点位数+1(四舍五入舍去)
double tempResult = Double.parseDouble(temp.substring(0, count)); //将String转换成double,并截取多一位用于四舍五入
double power = Math.pow(10, lengthOfDec); //求10的几次方用来四舍五入
double finalResult = (double) (Math.round(tempResult * power)) / power; //四舍五入
Log.i("result", x + "-" + y + "=" + finalResult);//此处的长度取决于小数点后面位数大的
return finalResult;
}
int getLengthOfInt(double x, double y) {
int lengthOfInt;
int intX = (int) x; //x的整数部分
int intY = (int) y; //y的整数部分
lengthOfInt = String.valueOf(intX - intY).length(); //结果整形部分的位数 = 相减后整形的位数
return lengthOfInt;
}
int getLengthOfDecimal(double x) {
return String.valueOf(x).split("\\.")[1].length(); //计算x小数点后面的位数
}
public class Result {
public static double getRes(String expression) {
System.out.println(expression.length());
expression = expression.replace("sin", "s");
expression = expression.replace("÷", "/");
expression = expression.replace("×", "*");
ArrayStack stack=new ArrayStack(20);
String exp = "";
int count = 0;
char[] chars = expression.toCharArray();
while (count < chars.length) {
if (count == 0 && chars[count] == '-') {
chars[count] = '#';
}
if (count >= 1 && chars[count] == '-' && chars[count - 1] == '(') {
chars[count] = '#';
}
if (count >= 1 && chars[count] == '-' && stack.priority(chars[count-1])>stack.priority(chars[count])) {
chars[count] = '#';
}
exp += chars[count];
count++;
}
expression=exp;
//创建两个栈,数栈,一个符号栈
ArrayStack numStack = new ArrayStack(20);
ArrayStack operatorStack = new ArrayStack(20);
//定义需要的相关变量
int index = 0;//用于扫描
double num1 = 0;
double num2 = 0;
int oper = 0;
double res = 0;
char ch = ' '; //将每次扫描得到char保存到ch
String keepNum = ""; //用于拼接 多位数
//开始while循环的扫描expression
while (true) {
//依次得到expression 的每一个字符
ch = expression.substring(index, index + 1).charAt(0);
//判断ch是什么,然后做相应的处理
if (operatorStack.isLeftBrackets(ch)) { //如果是左括号
//直接入符号栈..
operatorStack.push(ch);
} else if (operatorStack.isRightBrackets(ch)) { //如果是右括号
while (operatorStack.peek() != '(') { //循环直到能够到达 '(' 处
oper = (int) operatorStack.pop();
if (oper == 's' ||
oper == '!' ||
oper == 'v' ||
oper == '#' ||
oper == '%') { //如果栈顶为三角函数、阶乘或者是开根
num1 = numStack.pop();
res = numStack.mixedOperation(num1, oper);
//把运算的结果如数栈
numStack.push(res);
} else {
num1 = numStack.pop();
num2 = numStack.pop();
res = operatorStack.cal(num1, num2, oper);
//把运算的结果如数栈
numStack.push(res);
}
}
//然后将当前栈顶的操作符出符号栈----其实也就是 '(' 出栈
operatorStack.pop();
} else if (operatorStack.isOper(ch)) { //如果是运算符
if (operatorStack.isEmpty() || operatorStack.peek() == '(') {
//如果符号栈为空,或者栈顶为'('
operatorStack.push(ch);
} else if (operatorStack.priority(ch) > operatorStack.priority((int) operatorStack.peek())) {
//如果当前优先级比栈顶优先级高,直接入符号栈.
operatorStack.push(ch);
} else {
while (!operatorStack.isEmpty() &&
(operatorStack.priority(ch) <= operatorStack.priority((int) operatorStack.peek()))) {
oper = (int) operatorStack.pop();
if (!operatorStack.isEmpty() && (operatorStack.peek() == '!' ||
operatorStack.peek() == 's' ||
operatorStack.peek() == 'v' ||
operatorStack.peek() == '#' ||
operatorStack.peek() == '%'
)) {
num1 = numStack.pop();
res = numStack.mixedOperation(num1, oper);
numStack.push(res);//入栈
} else {
if (oper == 's' ||
oper == '!' ||
oper == 'v' ||
oper == '#' ||
oper == '%') { //如果栈顶为三角函数、阶乘或者是开根
num1 = numStack.pop();
res = numStack.mixedOperation(num1, oper);
//把运算的结果如数栈
numStack.push(res);
} else {
num1 = numStack.pop();
num2 = numStack.pop();
res = numStack.cal(num1, num2, oper);
//把运算的结果如数栈
numStack.push(res);
}
}
}
//然后将当前的操作符入符号栈
operatorStack.push(ch);
}
} else if (operatorStack.isPoint(ch) || operatorStack.isNum(ch)) { //如果是数或者是小数点,则直接入数栈
//numStack.push(ch - 48); // "1+3" '1' => 1
//1. 当处理多位数时,不能发现是一个数就立即入栈,因为可能是多位数
//2. 在处理数,需要向expression的表达式的index 后再看一位,如果是数就进行扫描,如果是符号才入栈
//3. 因此我们需要定义一个变量 字符串,用于拼接
//处理多位数
keepNum += ch;
//如果ch已经是expression的最后一位,就直接入栈
if (index == expression.length() - 1) {
numStack.push(Double.parseDouble(keepNum));
} else {
//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
//注意是看后一位,不是index++
if (operatorStack.isOper(expression.substring(index + 1, index + 2).charAt(0))
|| operatorStack.isRightBrackets(expression.substring(index + 1, index + 2).charAt(0))) {
//如果后一位是运算符,则入栈 keepNum = "1" 或者 "123"
numStack.push(Double.parseDouble(keepNum));
//最后keepNum必须清空
keepNum = "";
}
}
} else if (!operatorStack.isEmpty() && (operatorStack.peek() == 's' ||
operatorStack.peek() == '!' ||
operatorStack.peek() == 'v' ||
operatorStack.peek() == '#' ||
operatorStack.peek() == '%')) { //如果栈顶为三角函数算式、开根或者是阶乘
oper = (int) operatorStack.pop();
num1 = numStack.pop();
res = numStack.mixedOperation(num1, oper);
//把运算的结果入数栈
numStack.push(res);
}
//让index + 1, 并判断是否扫描到expression最后.
index++;
if (index >= expression.length()) {
break;
}
}
//当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
while (true) {
//如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】
if (operatorStack.isEmpty()) {
break;
}
if (operatorStack.peek() == 's' ||
operatorStack.peek() == '!' ||
operatorStack.peek() == 'v' ||
operatorStack.peek() == '#' ||
operatorStack.peek() == '%') { //如果栈顶为三角函数算式
oper = (int) operatorStack.pop();
num1 = numStack.pop();
res = numStack.mixedOperation(num1, oper);
numStack.push(res);//入栈
} else {
num1 = numStack.pop();
num2 = numStack.pop();
oper = (int) operatorStack.pop();
res = numStack.cal(num1, num2, oper);
numStack.push(res);//入栈
}
}
//将数栈的最后数,pop出,就是结果
double res2 = numStack.pop();
System.out.println(res2+"ll");
return res2;
}
求点赞+关注偶