0


Android——一个神奇的计算器APP

一个神奇的计算器APP

中缀运算

  1. 中缀运算定义了两个栈,数字栈和符号栈;分别存储用户输入的数字(例如:123)和输入的符号(例如:+,-);
  2. 下列视频以1+2+3/2*3%3为例;首先输入1,然后输入+,通过对运算符点击事件监听,将其分别纳入数字栈和符号栈,然后在输入2和+,即对+进行监听,并取出符号栈栈顶元素,判断其是否为初始化元素,若为否,则将数字栈栈顶元素取出,并获取拼接字符作为另外一个运算数字;(数字栈栈顶元素 &(代表符号栈栈顶元素)拼接字符串)(1+2);得到结果3之后将其压入数字栈中,并将第二个+号压入符号栈,用于下次运算;以此类推…

效果视频

运算

自定义圆形TextView

效果图

在这里插入图片描述

建立attr文件

通过对控件手势动作进行监听,改变按钮的样式;即按下为白色,松开为橙色

  1. <resources>
  2. <declare-styleable name="SetCircle">
  3. <attr name="CircleColor" format="color"/>
  4. <attr name="SelectCircle" format="color"/>
  5. </declare-styleable>
  6. </resources>

绘制圆形

  1. protected void onDraw(Canvas canvas) {
  2. //判断手势动作,改变控件状态
  3. if (isSelect){
  4. CirclePaint.setColor( SelectCircle );
  5. }else {
  6. CirclePaint.setColor( CircleColor );
  7. }
  8. //设置填充方式
  9. CirclePaint.setStyle( Paint.Style.FILL );
  10. //设置抗锯齿
  11. CirclePaint.setAntiAlias( true );
  12. RectF rectF = new RectF();
  13. //设置半径,比较长宽,取最大值
  14. int radius = getMeasuredWidth() > getMeasuredHeight() ? getMeasuredWidth() : getMeasuredHeight();
  15. rectF.set(getPaddingLeft(),getPaddingTop(),radius-getPaddingRight(),radius-getPaddingBottom());
  16. //绘制圆弧
  17. canvas.drawArc(rectF,0,360,false,CirclePaint);
  18. super.onDraw(canvas);
  19. }

字符拼接

通过StringBuilder将用户输入的数字进行拼接,段尾对复位按钮进行判断,将数字栈和符号栈以及拼接字符串的内容全部清空;

  1. private class NumOnClick implements View.OnClickListener{
  2. @Override
  3. public void onClick(View view) {
  4. switch (view.getId()){
  5. case R.id.Zero:
  6. numBuilder.append('0');
  7. break;
  8. case R.id.One:
  9. numBuilder.append('1');
  10. break;
  11. case R.id.Two:
  12. numBuilder.append('2');
  13. break;
  14. case R.id.Three:
  15. numBuilder.append('3');
  16. break;
  17. case R.id.Four:
  18. numBuilder.append('4');
  19. break;
  20. case R.id.Five:
  21. numBuilder.append('5');
  22. break;
  23. case R.id.Six:
  24. numBuilder.append('6');
  25. break;
  26. case R.id.Seven:
  27. numBuilder.append('7');
  28. break;
  29. case R.id.Eight:
  30. numBuilder.append('8');
  31. break;
  32. case R.id.Nine:
  33. numBuilder.append('9');
  34. break;
  35. case R.id.Point:
  36. numBuilder.append('.');
  37. break;
  38. case R.id.Reset:
  39. isReset = true;
  40. }
  41. if (isReset){
  42. PopStack();
  43. numBuilder.delete(0,numBuilder.length());
  44. ResultBox.setText("0");
  45. operatorStack.push('#');
  46. isReset = false;
  47. }else {
  48. ResultBox.setText(numBuilder.toString());
  49. }
  50. }
  51. }

清空栈内元素

清空数字栈和符号栈内元素

  1. private void PopStack(){
  2. while (numStack.isEmpty()){
  3. numStack.pop();
  4. }
  5. while (operatorStack.isEmpty()){
  6. operatorStack.pop();
  7. }
  8. }

运算执行

手势监听

此处以加运算符为例,对按下和松开两个事情进行监听,分别改变控件样式,并传入相应运算符进行运算

  1. private class OperatorOnClick implements View.OnTouchListener{
  2. @Override
  3. public boolean onTouch(View view, MotionEvent motionEvent) {
  4. boolean isPress = false;
  5. if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
  6. isPress = true;
  7. }
  8. switch (view.getId()){
  9. case R.id.Add:
  10. if (isPress){
  11. mAdd.IsSelect(true);
  12. mAdd.setTextColor(getResources().getColor(R.color.normal));
  13. StartOperation(ADD);
  14. }else {
  15. mAdd.IsSelect(false);
  16. mAdd.setTextColor(getResources().getColor(R.color.select));
  17. }
  18. break;

入栈&&出栈

在初始化时,将符号栈压入‘#’符号,即代表第一次执行,不进行结果运算

  1. operatorStack.push('#');
  1. 第一次运行时,即将符号栈栈顶元素取出,即‘#’,假如输入1和+,此时无法构成算式,因为确实另外一个运算数,即直接将其压入栈中,不进行结果运算;然后将拼接字符串清空,因为假如输入完了100和+,因为+号是不显示在用户界面的,如果不进行清空,之后输入的字符会追加在其之后,例如在输入50,即不清空为10050,会造成用户体验不良以及使用麻烦等缺点;

假如输入了100和+,然后输入50和-,构成100+50-算式,第一次不进行运算,如上释所示,第二次输入的-,即取出符号栈顶元素+,和运算数100和50,并将其传入EXEOperation()方法,开始运算结果

  1. private void StartOperation(char symbol){
  2. char operator = operatorStack.pop();
  3. if (operator == EQUAL){
  4. operatorStack.push(symbol);
  5. } else if (operator == '#'){
  6. numStack.push(numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
  7. operatorStack.push(symbol);
  8. numBuilder.delete(0,numBuilder.length());
  9. }else {
  10. switch (operator){
  11. case ADD:
  12. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),ADD);
  13. break;
  14. case SUB:
  15. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),SUB);
  16. break;
  17. case MULTIPLY:
  18. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MULTIPLY);
  19. break;
  20. case DIVISION:
  21. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),DIVISION);
  22. break;
  23. case MOD:
  24. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MOD);
  25. break;
  26. case EQUAL:
  27. EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
  28. break;
  29. }
  30. }
  31. }

运算结果

三个参数分别为第一个运算数,和另外一个运算数,以及符号栈栈顶元素,对符号进行判断,并进行结果运算,然后将结果压入栈中以及第二个运算符压人符合栈;
重点在于对等于键进行判断:
1:例如输入算式1+1-,对第二个运算符进行监听即可得到前一结果,然后在输入数字,符号,得到前一结果…
2:例如输入算式1+1=,此时并没有对等于符号进行监听,无法完成运算,解决办法为不将等于压入符号栈,直接结果入栈,相当于需要执行第一步才能完成运算

小数位判断

对结果字符串进行子串截取,判断小数点之后是否存在小数位,因为为double类型,默认会存在小数位。例如:
(1)1.0,则省略小数点后的0,直接输出0;
(2)1.05,则不进行小数位省略,直接输出

  1. //判断小数位之后是否有数字
  2. if (str.substring(str.indexOf('.') + 1, str.length() - 1).isEmpty()) {
  3. str = str.substring(0, str.indexOf('.'));
  4. }

运算代码

  1. private void EXEOperation(double front,double rear,char operator) {
  2. double result = 0;
  3. String str;
  4. /**
  5. * 对连续点击运算符,而运算数字并未符合标准时进行判断
  6. * 例如:12+
  7. * 此时12和+分别进栈,此时若再点击运算符+,则无法进行运算,因为rear运算数为空*/
  8. switch (operator) {
  9. case ADD:
  10. result = front + rear;
  11. break;
  12. case SUB:
  13. result = front - rear;
  14. break;
  15. case MULTIPLY:
  16. result = front * rear;
  17. break;
  18. case DIVISION:
  19. result = front / rear;
  20. break;
  21. case MOD:
  22. result = front < rear ? front :front % rear;
  23. break;
  24. }
  25. numStack.push(result);
  26. if (isReturn){
  27. operatorStack.push(EQUAL);
  28. }else {
  29. operatorStack.push(operator);
  30. isReturn = false;
  31. }
  32. str = String.valueOf(result);
  33. //判断小数位之后是否有数字
  34. if (str.substring(str.indexOf('.') + 1, str.length() - 1).isEmpty()) {
  35. str = str.substring(0, str.indexOf('.'));
  36. }
  37. ResultBox.setText(str);
  38. //前运算符清空,为后运算符输入做准备
  39. numBuilder.delete(0,numBuilder.length());
  40. }

任意进制转换

通过输入十进制数,分别转化为相应的二进制,八进制,十六进制数

效果视频

转换进制

进制转换

因为需要分别转化多个进制,无法对其数组长度进行判断,即将每个数字首元素作为存储数组长度的地址

  1. private int[] Conversion(int num,int binary){
  2. int[] remainder = new int[255];
  3. int count = 1;
  4. do {
  5. remainder[count++] = num%binary;
  6. num /= binary;
  7. } while (num != 0);
  8. remainder[0] = count;
  9. return remainder;
  10. }

结果逆置

通过对解析的进制数组进行逆置,因为十六进制的10——A,11——B…,所以需要对其进行判断,然后使用字符串拼接,最终返回一个结果字符串

  1. private String Inversion(int[] array){
  2. StringBuilder builder = new StringBuilder();
  3. for (int i = array[0]-1; i >=1 ; i--) {
  4. if (array[i] == 10){
  5. builder.append("A");
  6. }else if (array[i] == 11){
  7. builder.append("B");
  8. }else if (array[i] == 12){
  9. builder.append("C");
  10. }else if (array[i] == 13){
  11. builder.append("D");
  12. }else if (array[i] == 14){
  13. builder.append("E");
  14. }else if (array[i] == 15){
  15. builder.append("F");
  16. }else {
  17. builder.append(array[i]);
  18. }
  19. }
  20. return builder.toString();
  21. }

结果返回

  1. int num = Integer.parseInt(ResultBox.getText().toString());
  2. Binary_2.setText(Inversion(Conversion(num,2)));
  3. Binary_8.setText(Inversion(Conversion(num,8)));
  4. Binary_10.setText(Inversion(Conversion(num,10)));
  5. Binary_16.setText(Inversion(Conversion(num,16)));

本文转载自: https://blog.csdn.net/News53231323/article/details/123234328
版权归原作者 FranzLiszt1847 所有, 如有侵权,请联系我们删除。

“Android&mdash;&mdash;一个神奇的计算器APP”的评论:

还没有评论