Finalize the (faulty ChatGPT) calculator (advice)

This calculator code was written by ChatGPT.
The external design turned out fine.


The extension is also normally assembled by the Rush program.
But with the calculations, I was not able to get a positive result.
Let's take a simple example of 1+3 , the calculator gives the answer 13.0.
And so on, all simple calculations, with errors.
Do you have any idea how to fix this in this code?

    @SimpleFunction(description = "1. The `Calculator` function is the entry point for invoking the calculator. It calls the `CalculatorText` function, passing an `identify` parameter.\n" +
            "\n" +
            "2. The `CalculatorText` function initializes the layout components and creates the calculator UI. It sets up the `AlertDialog.Builder`, creates a vertical `LinearLayout` as the main container for the calculator UI, and initializes the `expressionTextView` and `resultTextView` for displaying the expression and result.\n" +
            "\n" +
            "3. The `valuesHex` array stores the labels for the calculator buttons, including numbers, operators (+, -, *, /), and special buttons like \"DEL\" and \"=\".\n" +
            "\n" +
            "4. The function sets up the button layout using nested `LinearLayouts`. It iterates over the `valuesHex` array and creates `Button` objects for each label. It also dynamically adjusts the layout parameters based on the button label. Buttons with labels \"+\", \"=\", and \"DEL\" have a width of 2 units, while others have a width of 1 unit. This ensures that these buttons appear wider in the layout.\n" +
            "\n" +
            "5. Each button click is handled by an `OnClickListener`. When a button is clicked, the corresponding button label is retrieved. If the button label is \"=\", the expression is evaluated using the `evaluateExpression` function, and the result is displayed in the `resultTextView`. The expression and expression display are cleared for the next calculation. If the button label is \"DEL\", the last character of the expression is deleted. For other buttons, the corresponding label is appended to the expression, and the expression display is updated.\n" +
            "\n" +
            "6. The `evaluateExpression` function takes the expression as input, removes any non-digit characters except the decimal point, and then evaluates the expression using stacks for operators and operands. It splits the expression into numbers and operators, performs the necessary calculations, and returns the final result.\n" +
            "\n" +
            "7. The `hasPrecedence` function checks the precedence of two operators based on their order of evaluation.\n" +
            "\n" +
            "8. The `evaluateTopOperator` function performs the evaluation of the top operator in the stack and updates the operand stack accordingly.\n" +
            "\n" +
            "Overall, this code creates a calculator UI with dynamically sized buttons and handles button clicks to build and evaluate mathematical expressions. The expression and result are displayed in the respective text views.")
    public void Calculator(final int identify) {
        CalculatorText(identify);
    }

    private void CalculatorText(final int identify) {
        // Define the buttons and their labels
        String[] valuesHex = {"7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", ".", "0", "+", "+", "DEL", "="};

        // Create a StringBuilder to store the input expression
        StringBuilder expressionBuilder = new StringBuilder();

        // Create the layout components
        AlertDialog.Builder alert = new AlertDialog.Builder(this.activity);
        LinearLayout layout = new LinearLayout(activity);
        layout.setOrientation(LinearLayout.VERTICAL);

        int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
        int commonBlockWidth = (int) (screenWidth * 0.8); // Adjust the width as needed (e.g., 80% of the screen width)
        LinearLayout.LayoutParams linear_fill_wrap = new LinearLayout.LayoutParams(
                commonBlockWidth,
                LinearLayout.LayoutParams.WRAP_CONTENT
        );


        // Create the TextView to display the expression and result
        TextView expressionTextView = new TextView(activity);
        expressionTextView.setLayoutParams(linear_fill_wrap);
        expressionTextView.setGravity(Gravity.CENTER);
        expressionTextView.setTextSize(24);
        expressionTextView.setPadding(10, 6, 10, 22);
        expressionTextView.setText(""); // Initially, no expression
        layout.addView(expressionTextView);

        TextView resultTextView = new TextView(activity);
        resultTextView.setLayoutParams(linear_fill_wrap);
        resultTextView.setGravity(Gravity.CENTER);
        resultTextView.setTextSize(24);
        resultTextView.setPadding(10, 6, 10, 22);
        resultTextView.setText(""); // Initially, no result
        layout.addView(resultTextView);

        // Create the button layout
        LinearLayout horizontalLayout = null;
        int buttonCount = 0;
        final int numberOfButtons = 4; // Number of buttons per row
        for (int i = 0; i < valuesHex.length; i++) {
            if (buttonCount % numberOfButtons == 0) {
                horizontalLayout = new LinearLayout(activity);
                horizontalLayout.setOrientation(LinearLayout.HORIZONTAL);
                horizontalLayout.setWeightSum(numberOfButtons);
                layout.addView(horizontalLayout, linear_fill_wrap);
            }

            Button button = new Button(activity);
            button.setText(valuesHex[i]);
            LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(
                    0,
                    LinearLayout.LayoutParams.WRAP_CONTENT,
                    valuesHex[i].equals("+") || valuesHex[i].equals("=") || valuesHex[i].equals("DEL") ? 2 : 1
            );
            button.setLayoutParams(buttonParams);

            int finalI = i;
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String buttonText = valuesHex[finalI];
                    if (buttonText.equals("=")) {
                        // Evaluate the expression and display the result
                        double result = evaluateExpression(expressionBuilder.toString());
                        resultTextView.setText(String.valueOf(result));
                        expressionBuilder.setLength(0); // Clear the expression
                        expressionTextView.setText(""); // Clear the expression display
                    } else if (buttonText.equals("DEL")) {
                        // Delete the last character from the expression
                        if (expressionBuilder.length() > 0) {
                            expressionBuilder.deleteCharAt(expressionBuilder.length() - 1);
                            expressionTextView.setText(expressionBuilder.toString());
                        }
                    } else {
                        expressionBuilder.append(buttonText);
                        expressionTextView.setText(expressionBuilder.toString());
                    }
                }
            });

            horizontalLayout.addView(button);
            buttonCount++;
        }

        alert.setMessage("Calculator");

        alert.setView(layout);
        alert.show();
    }

    private double evaluateExpression(String expression) {
        // Remove any non-digit characters except for the decimal point
        expression = expression.replaceAll("[^\\d.]", "");

        // Create stacks for operators and operands
        Stack<String> operatorStack = new Stack<>();
        Stack<Double> operandStack = new Stack<>();

        // Split the expression into numbers and operators
        String[] tokens = expression.split("(?<=\\d)(?=\\D)|(?<=\\D)(?=\\d)");

        for (String token : tokens) {
            if (token.matches("[+\\-*/]")) {
                // Operator
                while (!operatorStack.empty() && hasPrecedence(token, operatorStack.peek())) {
                    evaluateTopOperator(operatorStack, operandStack);
                }
                operatorStack.push(token);
            } else {
                // Operand
                operandStack.push(Double.parseDouble(token));
            }
        }

        // Evaluate any remaining operators
        while (!operatorStack.empty()) {
            evaluateTopOperator(operatorStack, operandStack);
        }

        // The final result will be at the top of the operand stack
        return operandStack.pop();
    }

    private boolean hasPrecedence(String op1, String op2) {
        // Check operator precedence
        return (op2.equals("*") || op2.equals("/")) && (op1.equals("+") || op1.equals("-"));
    }

    private void evaluateTopOperator(Stack<String> operatorStack, Stack<Double> operandStack) {
        String operator = operatorStack.pop();
        double operand2 = operandStack.pop();
        double operand1 = operandStack.pop();

        switch (operator) {
            case "+":
                operandStack.push(operand1 + operand2);
                break;
            case "-":
                operandStack.push(operand1 - operand2);
                break;
            case "*":
                operandStack.push(operand1 * operand2);
                break;
            case "/":
                operandStack.push(operand1 / operand2);
                break;
        }
    }

Did you ask Chat the same question?

Yes, I have tried to explain the problem in every possible way,
but the bot "assumes" that there is no error in the arithmetic,
I could not ask such a question to eliminate this defect.

Perhaps abandon the faulty ChatGPT advice and use the App Inventor Math Blocks instead Math blocks ?

Check without this line:

expression = expression.replaceAll("[^\\d.]", "");

1 Like

So what's the point of this extension? to learn how to write extension? to solve a real problem about calculator? to test the ChatGPT?

1 Like

@Patryk_F thanks, it works
you found the cause!
Perhaps there should be a similar parameter

expression = expression.replace("[^\\d.]", "");

and that would work too.

Interestingly, I asked about 20 clarifying questions, the bot did not understand me, before that there were hundreds of questions from my side, the bot's advice was always with the expected result and sometimes more than I expected.

@Kevinkun You're right. All of your questions represent almost all of my goals in making this calculator.
But before creating the calculator, I was engaged,
almost the same extension

own window with a keyboard to write the MAC address.
This was also done with the help of a bot.
As for me, the bot did everything perfectly.
He looks like this for me.

After successfully creating an extension for writing MAC AND IP addresses,
I, out of "sport interest" tried to use ChatGPT further by creating a calculator.
I understand perfectly well that the calculator I am creating is primitive, it is not for professional use.
Unfortunately I didn't manage it myself.
Thanks for the tips, this is a good lesson for me.

Yes, regex would have to accept math operators as well.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.