[英]Android calculator App good practice?
大家好我是Android世界的新手,我正在努力構建我猜一個中等難度的計算器應用程序。 我提出了這種結構,但沒有實現任何東西,因為我有點懷疑這是否是正確的方法。 所以我走了:
我有一個操作數界面,帶有一種叫做“getValue()”的方法,應該返回一個double類型,以及一些實現該接口的其他對象,從而實現“getValue()”方法:
表達式 ,我想過將這個對象作為一個私有成員字段來存儲所有的操作,所以這個表達式對象會有這樣的東西:
public class Expression implements Operand { private List<Operation> operationList; ... }
operationList將是一個ArrayList,其中Operation是另一個對象,它將涉及兩個操作數(因此兩個操作數接口作為類型)與一個Operator對象綁定在一起,該對象具有一個枚舉類型,表明涉及這兩個操作數的操作是否為SUM,DIV ,MUL或SUB。 就像是:
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)”這樣的表達式中使用子表達式,也會像操作數一樣評估操作數,特別是在此案件:
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
實現Operand的Number類,它將是double值的簡單Wrapper類,並且將在它實現的getValue()方法中返回該double。
具有枚舉類型的函數類,如果它是SIN,COS,TAN,ARCSIN,ARCCOS,ARCTAN,LOG或LN函數,則始終使用getValue()方法返回函數計算的雙重結果;
實用程序,這個類可能會被誤解:它是一個類,用於取冪,平方根,數字的百分比或它的階乘等操作。 這里的想法是再次使用枚舉類型來區分操作類型。 我知道取冪是一個操作本身但我看起來更好,使它遠離前面解釋的操作類導致結構和計算不同(我想將指數視為操作數類型,而不是操作對我來說,一個操作只涉及兩個操作數和一個操作符,如前所述)。
然后我知道,給出一個表達式:
3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2
數據結構將是:
Operand Operand
| |
3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2
| ¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Operand Operand
4個操作數,因此3個操作,但我需要建立優先級,所以我認為我應該遍歷operationList(Expression對象中的私有字段)來獲得這樣的優先級,因為我的數據結構會像(基於這個表達式,偽代碼):
列表:
- 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));
迭代此列表我可以發現操作號2(項目編號2)必須在操作編號1之前執行。但我認為這種方式不太好因為你看我每次都需要整理所有的ArrayList當執行操作N°2並獲得雙重結果時,從操作原因獲取結果,我需要為該結果創建一個Number()對象,以像操作數一樣再次處理它,並以操作的方式重新組織ArrayList第一個沒有Number(4)作為第二個操作數,但是包含在Number對象中的Operation 2 getResult()的新結果。 此外,位置3處的操作不再具有表達式作為第一個操作數,而是將前一個操作的結果作為操作數。
在我看來,這種結構的處理有點貴,我問的是,是否有人面臨同樣的問題,並提出了更好的解決方案,或者這個解決方案可能沒問題。 另一種方法是將完整的Expression存儲為String,並使用RegExp對其進行解析,以按順序確定所有操作。 這是一個更好的解決方案,因為我想讓用戶在他輸入表達式時動態更改操作數,即如果他寫了上一個表達式:
3 + 4 * ((5 + 2) - √4 + sin(4) + 3²) / 2
如果他想要點擊“等於”按鈕執行操作,他可以將√4更改為ln(6)。 所以我想使用以前的ArrayList會很難管理這樣的改變,因為我需要保持我的表達式的每個操作數的位置...
例如Google如何在他的計算器應用程序中執行此操作,例如,如果您查看 - > 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,但我猜每種語言的邏輯都是一樣的。
您認為可能的解決方案是什么? 謝謝你的關注!
編輯:我不明白的事情:
/**
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:
Function compileSimple(Symbols symbols, String expression) throws SyntaxException {
rpn.setConsumer(simpleCodeGen.setSymbols(symbols));
lexer.scan(expression, rpn);
return simpleCodeGen.getFun();
}
它返回一個Function對象,然后在其上調用eval()方法。 看看Function.eval()方法,我看到了這個:
/**
Evaluates an arity-0 function (a function with no arguments).
@return the value of the function
*/
public double eval() {
throw new ArityException(0);
}
方法eval必須返回一個double類型,並且實現拋出一個具有此實現的ArityException:
public class ArityException extends RuntimeException {
public ArityException(String mes) {
super(mes);
}
public ArityException(int nArgs) {
this("Didn't expect " + nArgs + " arguments");
}
}
它如何評估String並在拋出ArityException時返回double?
您可能想看一下隨平台打包的官方Android計算器應用程序的源代碼。
我認為Logic.java將是您正在尋找的類。 它具有格式化代碼,檢查運算符,估值等: Android計算器
編輯
Android計算器使用Arity Arithmetic Engine,它是一個開源庫,用於評估表示為字符串的算術表達式。 我無法找到該項目的活動鏈接,它已從code.google.com中刪除。 但您可以參考以下鏈接獲取更多信息:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.