Android: una aplicación de calculadora mágica

operación infija

        La operación de infijos define dos pilas, la pila de números y la pila de símbolos; almacenan respectivamente los números ingresados ​​por el usuario (por ejemplo: 1, 2, 3) y los símbolos (por ejemplo: +, -);
        el siguiente video usa 1 +2+3 /2*3%3 como ejemplo; primero ingrese 1, luego ingrese +, al monitorear el evento de clic del operador, colóquelos en la pila digital y la pila de símbolos respectivamente, y luego ingrese 2 y +, es decir, monitor +, y saque el elemento superior de la pila de símbolos, para determinar si es un elemento de inicialización, si no, saque el elemento superior de la pila digital, y obtenga el carácter empalmado como otro número aritmético; (el elemento superior de la pila digital & (representa el elemento superior de la pila de símbolos) cadenas de empalme) (1+2); después de obtener el resultado 3, introdúzcalo en la pila de números y presione el segundo signo + en la pila de símbolos para la siguiente operación, y así sucesivamente...

efecto de vídeo

operación

TextView circular personalizado

representaciones

inserte la descripción de la imagen aquí

Crear archivo attr

Cambie el estilo del botón al monitorear la acción del gesto del control; es decir, blanco cuando se presiona y naranja cuando se suelta

<resources>
    <declare-styleable name="SetCircle">
        <attr name="CircleColor" format="color"/>
        <attr name="SelectCircle" format="color"/>
    </declare-styleable>
</resources>

dibuja un circulo


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

empalme de personajes

Los números ingresados ​​por el usuario se empalman a través de StringBuilder, el botón de reinicio se juzga al final del segmento, y la pila de números, la pila de símbolos y el contenido de la cadena empalmada se borran;

private class NumOnClick implements View.OnClickListener{
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.Zero:
                    numBuilder.append('0');
                    break;
                case R.id.One:
                    numBuilder.append('1');
                    break;
                case R.id.Two:
                    numBuilder.append('2');
                    break;
                case R.id.Three:
                    numBuilder.append('3');
                    break;
                case R.id.Four:
                    numBuilder.append('4');
                    break;
                case R.id.Five:
                    numBuilder.append('5');
                    break;
                case R.id.Six:
                    numBuilder.append('6');
                    break;
                case R.id.Seven:
                    numBuilder.append('7');
                    break;
                case R.id.Eight:
                    numBuilder.append('8');
                    break;
                case R.id.Nine:
                    numBuilder.append('9');
                    break;
                case R.id.Point:
                    numBuilder.append('.');
                    break;
                case R.id.Reset:
                    isReset = true;
            }
            if (isReset){
                PopStack();
                numBuilder.delete(0,numBuilder.length());
                ResultBox.setText("0");
                operatorStack.push('#');
                isReset = false;
            }else {
                ResultBox.setText(numBuilder.toString());
            }

        }
    }

Elementos de pila vacíos

Vaciar los elementos en la pila de números y la pila de símbolos

  private void PopStack(){
        while (numStack.isEmpty()){
            numStack.pop();
        }
        while (operatorStack.isEmpty()){
            operatorStack.pop();
        }
    }

ejecución de la operación

Monitoreo de gestos

Aquí tomamos el operador de suma como ejemplo, monitoreamos la presión y la liberación, cambiamos el estilo de control respectivamente y pasamos el operador correspondiente para la operación.

   private class OperatorOnClick implements View.OnTouchListener{

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            boolean isPress = false;
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                isPress = true;
            }
            switch (view.getId()){
                case R.id.Add:
                    if (isPress){
                        mAdd.IsSelect(true);
                        mAdd.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(ADD);
                    }else {
                        mAdd.IsSelect(false);
                        mAdd.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;

Empujar y hacer estallar

Durante la inicialización, inserte la pila de símbolos en el símbolo '#', lo que significa la primera ejecución y no se realiza ninguna operación de resultado.

operatorStack.push('#');

    Cuando se ejecuta por primera vez, se elimina el elemento superior de la pila de símbolos, es decir, '#'. Si se ingresan 1 y +, la fórmula no se puede formar en este momento, porque de hecho hay otro operando, es decir , se inserta directamente en la pila y el resultado no se realiza.Operación, luego borre la cadena concatenada, porque si se ingresan 100 y +, porque el signo + no se muestra en la interfaz de usuario, si no se borra, los caracteres ingresados ​​​​más tarde se agregarán después, por ejemplo, cuando se ingresa 50, es decir, no borrarlo en 10050 causará desventajas como una mala experiencia de usuario y un uso problemático;
  si ingresa 100 y +, y luego ingresa 50 y - para formar una fórmula 100+50-, la primera vez que no se realiza ningún cálculo, como se muestra en la explicación anterior, la segunda vez La entrada -, es decir, toma el elemento superior de la pila de símbolos +, y los operandos 100 y 50 y páselos al método EXEOperation() para iniciar el resultado del cálculo

   private void StartOperation(char symbol){
        char operator = operatorStack.pop();
        if (operator == EQUAL){
            operatorStack.push(symbol);
        } else if (operator == '#'){
            numStack.push(numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
            operatorStack.push(symbol);
            numBuilder.delete(0,numBuilder.length());
        }else {
            switch (operator){
                case ADD:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),ADD);
                    break;
                case SUB:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),SUB);
                    break;
                case MULTIPLY:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MULTIPLY);
                    break;
                case DIVISION:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),DIVISION);
                    break;
                case MOD:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MOD);
                    break;
                case EQUAL:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
                    break;
            }
        }
    }

resultado de la operación

  Los tres parámetros son el primer operando, otro operando y el elemento superior de la pila de símbolos, se juzga el símbolo y se calcula el resultado, y luego el resultado se empuja a la pila y el segundo operador se empuja para que coincida con Stack;
  la clave es juzgar la tecla igual:
    1: Por ejemplo, ingrese la fórmula 1+1-, controle el segundo operador para obtener el resultado anterior y luego ingrese números y símbolos para obtener el resultado anterior...
    2: Por ejemplo Ingrese la fórmula 1 + 1 =, en este momento, el símbolo igual no se controla y la operación no se puede completar. La solución es no empujar el igual a la pila de símbolos, y empujar directamente el resultado a la pila, que es equivalente al primer paso para completar la operación.

Juicio de lugar decimal

La interceptación de subcadena se realiza en la cadena de resultado para determinar si hay lugares decimales después del punto decimal. Debido a que es de tipo doble, hay lugares decimales de forma predeterminada. Por ejemplo:
(1) 1.0, omita el 0 después del punto decimal y genere 0 directamente;
(2) 1.05, no omita el lugar decimal y genere directamente

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

Código de operación

    private void EXEOperation(double front,double rear,char operator) {
        double result = 0;
        String str;
        /**
         * 对连续点击运算符,而运算数字并未符合标准时进行判断
         * 例如:12+
         * 此时12和+分别进栈,此时若再点击运算符+,则无法进行运算,因为rear运算数为空*/
        switch (operator) {
            case ADD:
                result = front + rear;
                break;
            case SUB:
                result = front - rear;
                break;
            case MULTIPLY:
                result = front * rear;
                break;
            case DIVISION:
                result = front / rear;
                break;
            case MOD:
                result = front < rear ? front :front % rear;
                break;
        }
        numStack.push(result);
        if (isReturn){
            operatorStack.push(EQUAL);
        }else {
            operatorStack.push(operator);
            isReturn = false;
        }
        str = String.valueOf(result);
        //判断小数位之后是否有数字
        if (str.substring(str.indexOf('.') + 1, str.length() - 1).isEmpty()) {
            str = str.substring(0, str.indexOf('.'));
        }
        ResultBox.setText(str);
        //前运算符清空,为后运算符输入做准备
        numBuilder.delete(0,numBuilder.length());
    }

conversión de base arbitraria

Al ingresar números decimales, conviértalos en números binarios, octales y hexadecimales correspondientes, respectivamente

efecto de vídeo

base de conversión

conversión básica

Debido a que varias bases deben convertirse por separado, no se puede juzgar la longitud de la matriz, es decir, el primer elemento de cada número se usa como la dirección para almacenar la longitud de la matriz.

   private int[] Conversion(int num,int binary){
     int[] remainder = new int[255];
     int count = 1;
     do {
         remainder[count++] = num%binary;
         num /= binary;
     } while (num != 0);
     remainder[0] = count;
     return remainder;
    }

inversión de resultados

Al invertir la matriz hexadecimal analizada, porque el hexadecimal 10-A, 11-B..., debe juzgarse y luego usar la concatenación de cadenas y finalmente devolver una cadena de resultado

    private String Inversion(int[] array){
            StringBuilder builder = new StringBuilder();
        for (int i = array[0]-1; i >=1 ; i--) {
            if (array[i] == 10){
                builder.append("A");
            }else if (array[i] == 11){
                builder.append("B");
            }else if (array[i] == 12){
                builder.append("C");
            }else if (array[i] == 13){
                builder.append("D");
            }else if (array[i] == 14){
                builder.append("E");
            }else if (array[i] == 15){
                builder.append("F");
            }else {
                builder.append(array[i]);
            }
        }
        return builder.toString();
    }

resultado devuelto

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

Supongo que te gusta

Origin blog.csdn.net/News53231323/article/details/123234328
Recomendado
Clasificación