关于java:Android计算器App好习惯?

Android calculator App good practice?

大家好,我是Android世界的新手,我正在尝试建立一个中等难度的计算器应用程序。我提出了这种结构,但还没有实现任何东西,因为我有点怀疑这是否是正确的方法。所以我走到这里:

我有一个操作数接口,它具有一种称为"getValue()"的方法,该方法应返回双精度类型,以及一些实现该接口的其他对象,因此实现了"getValue()"方法:

  • expression,我想用一个私有成员字段将其设置为一个对象,该字段将存储所有操作,因此这个expression对象将具有如下内容:

    1
    2
    3
    4
    5
    public class Expression implements Operand {

        private List<Operation> operationList;
        ...
    }

    operationList是一个arraylist,其中operation是另一个对象,它将涉及两个操作数(因此两个操作数接口作为类型),与一个具有枚举类型的运算符对象绑定在一起,该枚举类型表示涉及这两个操作数的操作是sum、div、mul或sub。类似于:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public class Operation {

        private Operand operand1;
        private Operand operand2;
        private Operator operator;          

        public Operation(Operand operand1, Operator operator, Operand operand2) {
             this.operand1 = operand1;
             this.operand2 = operand2;
             this.operator = operator;
        }

        public double getResult() {
             if (operator.getType() == Operator.Type.SUM) {
                 return operand1.getValue() + operand2.getValue();
             }
             else if (operator.getType() == Operator.Type.SUB) {
                 return operand1.getValue() - operand2.getValue();
             }
             else if (operator.getType() == Operator.Type.MUL) {
                 return operand1.getValue() * operand2.getValue();
             }
             else if (operator.getType() == Operator.Type.DIV) {
                 return operand1.getValue() / operand2.getValue();
             }
             return 0;
        }
        ...
    }

通过这种方式,即使在"3+(4*3-2*(4-1)/2+5)"这样的表达式中有一个子表达式,也会像操作数一样通过接口进行计算,特别是在这种情况下:

1
2
3
4
5
6
 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
  • 实现操作数的数字类,该操作数将是双精度值的简单包装类,并将在它实现的getValue()方法中返回该双精度值。

  • 一个枚举类型的函数类,表示它是sin、cos、tan、arcin、arcos、arctan、log或ln函数,始终使用getValue()方法返回函数计算的双重结果;

  • 实用程序,这个类可能会被误解:它是用于诸如求幂、平方根、数字百分比或其阶乘等操作的类。这里的想法是再次使用枚举类型来区分操作的类型。我知道求幂是一个操作本身,但我觉得最好是让它远离前面解释的操作类,因为结构和计算是不同的(我想把求幂看作一个操作数类型,而不是一个操作,对我来说,一个操作只涉及两个操作数和一个操作数。前D)。

然后我知道,给出如下表达式:

1
3 + 4 * ((5 + 2) -4 + sin(4) + 32) / 2

数据结构为:

1
2
3
4
5
  Operand                              Operand
    |                                  |  
3 + 4 * ((5 + 2) -4 + sin(4) + 32) / 2
|       ˉˉˉˉˉˉˉˉˉˉˉˉˉ|ˉˉˉˉˉˉˉˉˉˉˉˉˉˉ  
Operand             Operand

4个操作数,因此3个操作,但我需要确定优先级,所以我认为应该迭代operationlist(表达式对象中的私有字段)以获得这样的优先级,因为我的数据结构如下(基于此表达式,伪代码):

名单:

1
2
3
- 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) + 32"));
- Item n° 3 -> Operation(Expression("(5 + 2) - √4 + sin(4) + 32"), Operator(Operator.Type.DIV), Number(2));

通过对这个列表的迭代,我发现操作编号2(第2项)必须在操作编号1之前执行。但是我认为这种方法不太好,因为你看到我每次从操作中得到结果时都需要整理所有的arraylist,因为当操作n°2执行并得到双重结果时,我需要为该结果创建一个number()对象,以便将其再次视为操作数,并以操作num的方式重新组织arraylist。BER One不再将数字(4)作为第二个操作数,而是将操作2 getResult()的新结果包装在数字对象中。另外,位置3处的操作不再将表达式作为第一个操作数,而是将上一个操作的结果作为操作数。

在我看来,这种结构的处理成本有点高,我在问是否有人面临同样的问题,并提出了一个更好的解决方案,或者这个解决方案可能是好的。另一种方法是将完整表达式存储为字符串,并使用regexp对其进行分析,以确定所有操作的顺序。这是一个更好的解决方案吗?因为如果用户在键入表达式时(即,如果他编写了前一个表达式),我希望允许用户动态地更改操作数:

1
3 + 4 * ((5 + 2) -4 + sin(4) + 32) / 2

如果他想在单击"等于"按钮执行操作之前将√4更改为ln(6)。所以我想使用以前的数组列表很难管理这种变化,因为我需要保持表达式中每个操作数的位置…

例如,谷歌在他的计算器应用程序中是如何做到这一点的,例如,如果你查看->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

我知道这是javascript,但我想每种语言的逻辑都是一样的。

你认为可能的解决办法是什么?谢谢你的关注!

编辑:我不明白的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /**
       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();
    }

此方法调用编译器编译对象的.compilesImple:

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

它返回一个函数对象,然后调用eval()方法。看看这个函数。


你可能想看看官方Android计算器应用程序的源代码,它与平台一起打包。

我认为logic.java将是您要查找的类。它具有格式化、检查操作员、评估等代码:Android计算器

编辑

Android计算器使用arity算术引擎,该引擎是一个开放源代码库,用于评估用字符串表示的算术表达式。我找不到该项目的活动链接,它已从code.google.com中删除。但您可以参考以下链接了解更多信息:

  • http://www.developerfusion.com/project/62854/arity/
  • 下载arity.jar