Android calculator App good practice?
大家好,我是Android世界的新手,我正在尝试建立一个中等难度的计算器应用程序。我提出了这种结构,但还没有实现任何东西,因为我有点怀疑这是否是正确的方法。所以我走到这里:
我有一个操作数接口,它具有一种称为"getValue()"的方法,该方法应返回双精度类型,以及一些实现该接口的其他对象,因此实现了"getValue()"方法:
expression,我想用一个私有成员字段将其设置为一个对象,该字段将存储所有操作,因此这个expression对象将具有如下内容:
1
2
3
4
5public 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
29public 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 |
通过对这个列表的迭代,我发现操作编号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中删除。但您可以参考以下链接了解更多信息: