tonix
tonix

Reputation: 6939

Android calculator App good practice?

Hi everyone I am new in the Android world and I am trying to build I guess a medium difficulty calculator app. I came up with this kind of a structure, but didn't implement anything yet cause I'm a little bit in doubt if this could be the right way. So here I go:

I have an Operand interface with kind of a method called "getValue()" that should return a double type, and some other objects that implement that interface, thus implement that "getValue()" method:

In this way even with a sub-expression inside an expression like "3 + (4 * 3 - 2 * (4 - 1) / 2 + 5))" will be evaluated like an Operand thanks to the interface, in particular in this case:

 operator   All this is another Expression object (a sub-expression that is treated 
   |         |                                     like an Operand
   | ________|____________                         cause it implements the Operand
 3 + (4 * 3 - 2 * (4 - 1))                         interface).
 |
Operand operand1

Then I know that, given an Expression like:

3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2

The data structure would be:

  Operand                              Operand
    |                                  |   
3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2
|       ¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯  
Operand             Operand

4 operands, thus 3 operations, but I need to establish the priority, so I thought that I should iterate over the operationList (the private field in the Expression object) to get such a priority, cause my data structure would be like (based on this expression, pseudo code):

List:

- Item n° 1 -> Operation(Number(3), Operator(Operator.Type.SUM), Number(4));
- Item n° 2 -> Operation(Number(4), Operator(Operator.Type.MUL), Expression("(5 + 2) - √4 + sin(4) + 3²"));
- Item n° 3 -> Operation(Expression("(5 + 2) - √4 + sin(4) + 3²"), Operator(Operator.Type.DIV), Number(2));

Iterating over this List I can find that the Operation number 2 (Item n° 2) must be performed before the operation number 1. But I think this way is not so good cause you see I need to tidy up all the ArrayList every time I get the result from an Operation cause when the Operation N° 2 is performed and gets the double result, I need to create a Number() object for that result to treat it again like an Operand and reorganize the ArrayList in a way that the Operation number one has not Number(4) as a second operand anymore, but has the new result from the Operation 2 getResult() wrapped in a Number object. Also the Operation at position 3 has not an Expression as first operand anymore, but has the result from the previous operation as Operand.

It seems to me that kind of a structure is a little expensive to handle and I am asking if someone faced the same problem and came up with a better solution, or this solution may be fine. Another way is to store the complete Expression as a String and parse it with a RegExp to determine all the operation in sequence. Is it a better solution cause I would like to let the user change an Operand on the fly if while he is typing the expression, i.e. if he wrote the previous expression:

3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2

He could change the √4 to a ln(6) if he wants to do that before clicking the "Equals" button to perform the operation. So I guess using the previously ArrayList it would be difficult to manage such change, cause I would need to keep the position of each Operand of my Expression...

How does e.g. Google does this in his calculator app e.g. if you look at -> https://www.google.it/search?q=2%2B2&oq=2%2B2&aqs=chrome.0.69i59j0l2j69i65l2j0.1141j0j7&sourceid=chrome&es_sm=94&ie=UTF-8#q=+3+%2B+4+*+((5+%2B+2)+-+sin(4)+%2B+3)+%2F+2

I know it's Javascript but I guess the logic is the same for every language.

What do you think may be a possible solution? Thank you for the attention!

EDIT: something I did not understand:

  /**
       Evaluates a simple expression (such as "1+1") and returns its value.
       @throws SyntaxException in these cases:
       <ul>
       <li> the expression is not well-formed
       <li> the expression is a definition (such as "a=1+1")
       <li> the expression is an implicit function (such as "x+1")
       </ul>
     */
    public synchronized double eval(String expression) throws SyntaxException {
        return compiler.compileSimple(this, expression).eval();
    }

This method calls the .compileSimple of the Compiler compile object:

Function compileSimple(Symbols symbols, String expression) throws SyntaxException {
    rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
    lexer.scan(expression, rpn);
    return simpleCodeGen.getFun();
}

Which returns a Function object and then calls the eval() method on that. Looking at the Function.eval() method I saw this:

/**
       Evaluates an arity-0 function (a function with no arguments).
       @return the value of the function
    */
    public double eval() {
        throw new ArityException(0);
    }

The method eval must return a double type and the implementation throws an ArityException which has this implementation:

public class ArityException extends RuntimeException {
    public ArityException(String mes) {
        super(mes);
    }

    public ArityException(int nArgs) {
        this("Didn't expect " + nArgs + " arguments");
    }
}

How does it evaluates the String and returns a double if it throws an ArityException?

Upvotes: 3

Views: 1624

Answers (1)

Basant Singh
Basant Singh

Reputation: 5916

You might want to take a look a the source code of the official Android calculator app which comes packaged with the platform.

I think the Logic.java will be the class that you are looking for. It has the code for the formatting, checking for operators, valuation etc: Android Calculator

EDIT

The Android calculator uses the Arity Arithmetic Engine, which is an open source library for evaluating arithmetic expressions represented as strings. I was not able to find an alive link for the project, it has been removed from code.google.com. But you can refer to the following links for more info:

  1. http://www.developerfusion.com/project/62854/arity/
  2. Download arity .jar

Upvotes: 2

Related Questions