var activity
This commit is contained in:
parent
7fa8eb6f66
commit
454789a408
@ -37,7 +37,7 @@
|
||||
<EditText a:id="@+id/var_edit_value"
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="wrap_content"
|
||||
a:inputType="number"
|
||||
a:inputType="numberDecimal"
|
||||
a:textSize="20dp">
|
||||
</EditText>
|
||||
|
||||
|
@ -26,7 +26,10 @@ import org.solovyev.util.math.Complex;
|
||||
public class CalculatorModel {
|
||||
|
||||
@NotNull
|
||||
private final Interpreter interpreter;
|
||||
private Interpreter interpreter;
|
||||
|
||||
@NotNull
|
||||
private final Object interpreterMonitor = new Object();
|
||||
|
||||
private int numberOfFractionDigits = 5;
|
||||
|
||||
@ -38,30 +41,41 @@ public class CalculatorModel {
|
||||
|
||||
private static CalculatorModel instance;
|
||||
|
||||
private CalculatorModel(@Nullable Context context) throws EvalError {
|
||||
private CalculatorModel(@Nullable Context context) {
|
||||
load(context);
|
||||
|
||||
interpreter = new Interpreter();
|
||||
interpreter.eval(ToJsclPreprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
synchronized (interpreterMonitor) {
|
||||
try {
|
||||
interpreter = new Interpreter();
|
||||
interpreter.eval(ToJsclPreprocessor.wrap(JsclOperation.importCommands, "/jscl/editorengine/commands"));
|
||||
|
||||
/*for (Var var : varsRegister.getVars()) {
|
||||
if (!var.isSystem()) {
|
||||
exec(var.getName() + "=" + var.getValue() + ";");
|
||||
}
|
||||
}*/
|
||||
} catch (EvalError evalError) {
|
||||
throw new RuntimeException(evalError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String evaluate(@NotNull JsclOperation operation, @NotNull String expression) throws EvalError, ParseException {
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
/*
|
||||
for (Var var : varsRegister.getVars()) {
|
||||
if (!var.isSystem()) {
|
||||
sb.append(var.getName()).append("=").append(var.getValue()).append(";");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
sb.append(preprocessor.process(expression));
|
||||
|
||||
//Log.d(CalculatorModel.class.getName(), "Preprocessed expression: " + preprocessedExpression);
|
||||
|
||||
Object evaluationObject = interpreter.eval(ToJsclPreprocessor.wrap(operation, sb.toString()));
|
||||
final Object evaluationObject;
|
||||
synchronized (interpreterMonitor) {
|
||||
evaluationObject = interpreter.eval(ToJsclPreprocessor.wrap(operation, sb.toString()));
|
||||
}
|
||||
String result = String.valueOf(evaluationObject).trim();
|
||||
|
||||
try {
|
||||
@ -120,7 +134,7 @@ public class CalculatorModel {
|
||||
return MathUtils.round(dResult, numberOfFractionDigits);
|
||||
}
|
||||
|
||||
public synchronized void load(@Nullable Context context) {
|
||||
public synchronized void load(@Nullable Context context) {
|
||||
if (context != null) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
@ -154,7 +168,7 @@ public class CalculatorModel {
|
||||
}
|
||||
|
||||
public static CalculatorModel getInstance() {
|
||||
if (!isLoaded()) {
|
||||
if (!isLoaded()) {
|
||||
throw new RuntimeException("CalculatorModel must be instantiated!");
|
||||
}
|
||||
|
||||
@ -165,8 +179,34 @@ public class CalculatorModel {
|
||||
return instance != null;
|
||||
}
|
||||
|
||||
|
||||
private void exec(String str) throws EvalError {
|
||||
interpreter.eval(str);
|
||||
}
|
||||
|
||||
private String eval(String str) throws EvalError {
|
||||
return interpreter.eval(commands(str)).toString();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public VarsRegister getVarsRegister() {
|
||||
return varsRegister;
|
||||
}
|
||||
|
||||
String commands(String str) {
|
||||
return commands(str, false);
|
||||
}
|
||||
|
||||
String commands(String str, boolean found) {
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
int n = str.length() - cmds[i].length() - 1;
|
||||
if (n >= 0 && (" " + cmds[i].toLowerCase()).equals(str.substring(n)))
|
||||
return commands(str.substring(0, n), true) + "." + cmds[i] + "()";
|
||||
}
|
||||
str = str.replaceAll("\n", "");
|
||||
return found ? "jscl.math.Expression.valueOf(\"" + str + "\")" : str;
|
||||
}
|
||||
|
||||
static final String cmds[] = new String[]{"expand", "factorize", "elementary", "simplify", "numeric", "toMathML", "toJava"};
|
||||
}
|
||||
|
@ -177,10 +177,10 @@ public class CalculatorVarsActivity extends ListActivity {
|
||||
Toast.makeText(CalculatorVarsActivity.this, error, Toast.LENGTH_LONG).show();
|
||||
createEditVariableDialog(editedInstance, name, value, description);
|
||||
} else {
|
||||
if (editedInstance != null && !editedInstance.getName().equals(name)) {
|
||||
varsRegister.addVar(editedInstance.getName(), varBuilder);
|
||||
} else {
|
||||
if ( editedInstance == null ) {
|
||||
CalculatorVarsActivity.this.adapter.add(varsRegister.addVar(null, varBuilder));
|
||||
} else {
|
||||
varsRegister.addVar(editedInstance.getName(), varBuilder);
|
||||
}
|
||||
|
||||
varsRegister.save(CalculatorVarsActivity.this);
|
||||
|
@ -192,7 +192,7 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
|
||||
@Override
|
||||
public void doOperation(@NotNull EditText editor) {
|
||||
|
||||
final MathEntityType type = MathEntityType.getType(text);
|
||||
final MathEntityType type = MathEntityType.getType(text, 0);
|
||||
|
||||
int cursorPositionOffset = 0;
|
||||
final StringBuilder textToBeInserted = new StringBuilder(text);
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
* or visit http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/3/11
|
||||
* Time: 12:54 AM
|
||||
*/
|
||||
public class CharacterAtPositionFinder implements Finder<Character> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final String targetString;
|
||||
|
||||
public CharacterAtPositionFinder(@NotNull String targetString, int i) {
|
||||
this.targetString = targetString;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(@Nullable Character s) {
|
||||
return s != null && s.equals(targetString.charAt(i));
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
* or visit http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/3/11
|
||||
* Time: 12:49 AM
|
||||
*/
|
||||
public class StartsWithFinder implements Finder<String> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final String targetString;
|
||||
|
||||
public StartsWithFinder(@NotNull String targetString, int i) {
|
||||
this.targetString = targetString;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(@Nullable String s) {
|
||||
return targetString.startsWith(s, i);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
@ -19,46 +19,88 @@ public class ToJsclPreprocessor implements Preprocessor {
|
||||
@Override
|
||||
@NotNull
|
||||
public String process(@NotNull String s) {
|
||||
|
||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
boolean constantBefore = false;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
if ( MathEntityType.getType(ch) == MathEntityType.postfix_function ) {
|
||||
int start = getPostfixFunctionStart(s, i - 1);
|
||||
}
|
||||
}
|
||||
startsWithFinder.setI(i);
|
||||
|
||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s);
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
|
||||
checkMultiplicationSignBeforeFunction(sb, s, i);
|
||||
checkMultiplicationSignBeforeFunction(sb, s, i, constantBefore);
|
||||
constantBefore = false;
|
||||
|
||||
if (MathEntityType.openGroupSymbols.contains(ch)) {
|
||||
sb.append('(');
|
||||
} else if (MathEntityType.closeGroupSymbols.contains(ch)) {
|
||||
sb.append(')');
|
||||
} else if (ch == 'π') {
|
||||
sb.append("pi");
|
||||
} else if (ch == '×' || ch == '∙') {
|
||||
sb.append("*");
|
||||
} else {
|
||||
startsWithFinder.setI(i);
|
||||
final String function = CollectionsUtils.get(MathEntityType.prefixFunctions, startsWithFinder);
|
||||
if (function != null) {
|
||||
sb.append(toJsclFunction(function));
|
||||
i += function.length() - 1;
|
||||
} else if (ch == 'e') {
|
||||
sb.append("exp(1)");
|
||||
} else if (ch == 'i') {
|
||||
sb.append("sqrt(-1)");
|
||||
String entity = CollectionsUtils.get(MathEntityType.prefixFunctions, startsWithFinder);
|
||||
if (entity == null) {
|
||||
entity = CollectionsUtils.get(CalculatorModel.getInstance().getVarsRegister().getVarNames(), startsWithFinder);
|
||||
if (entity == null) {
|
||||
sb.append(ch);
|
||||
} else {
|
||||
sb.append(entity);
|
||||
i += entity.length() - 1;
|
||||
constantBefore = true;
|
||||
}
|
||||
} else {
|
||||
sb.append(ch);
|
||||
sb.append(toJsclFunction(entity));
|
||||
i += entity.length() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
return replaceVariables(sb.toString());
|
||||
}
|
||||
|
||||
private String replaceVariables(@NotNull final String s) {
|
||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, 0);
|
||||
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
startsWithFinder.setI(i);
|
||||
|
||||
int offset = 0;
|
||||
String functionName = CollectionsUtils.get(MathEntityType.prefixFunctions, startsWithFinder);
|
||||
if (functionName == null) {
|
||||
String varName = CollectionsUtils.get(CalculatorModel.getInstance().getVarsRegister().getVarNames(), startsWithFinder);
|
||||
if (varName != null) {
|
||||
final Var var = CalculatorModel.getInstance().getVarsRegister().getVar(varName);
|
||||
if (var != null) {
|
||||
result.append(var.getValue());
|
||||
offset = varName.length();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(functionName);
|
||||
offset = functionName.length();
|
||||
}
|
||||
|
||||
|
||||
if (offset == 0) {
|
||||
result.append(s.charAt(i));
|
||||
} else {
|
||||
i += offset - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void replaceVariables(StringBuilder sb, String s, int i, @NotNull StartsWithFinder startsWithFinder) {
|
||||
for (Var var : CalculatorModel.getInstance().getVarsRegister().getVars()) {
|
||||
if (!var.isSystem()) {
|
||||
if (s.startsWith(var.getName(), i)) {
|
||||
if (CollectionsUtils.get(MathEntityType.prefixFunctions, startsWithFinder) == null) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getPostfixFunctionStart(@NotNull String s, int position) {
|
||||
@ -66,17 +108,16 @@ public class ToJsclPreprocessor implements Preprocessor {
|
||||
|
||||
int numberOfOpenGroups = 0;
|
||||
int result = position;
|
||||
for ( ; result >= 0; result-- ) {
|
||||
char ch = s.charAt(result);
|
||||
for (; result >= 0; result--) {
|
||||
|
||||
final MathEntityType mathEntityType = MathEntityType.getType(ch);
|
||||
final MathEntityType mathEntityType = MathEntityType.getType(s, result);
|
||||
|
||||
if ( mathEntityType != null ) {
|
||||
if ( CollectionsUtils.contains(mathEntityType, MathEntityType.digit, MathEntityType.dot) ) {
|
||||
if (mathEntityType != null) {
|
||||
if (CollectionsUtils.contains(mathEntityType, MathEntityType.digit, MathEntityType.dot)) {
|
||||
// continue
|
||||
} else if (MathEntityType.closeGroupSymbols.contains(ch)) {
|
||||
} else if (MathEntityType.closeGroupSymbols.contains(s.charAt(result))) {
|
||||
numberOfOpenGroups++;
|
||||
} else if (MathEntityType.openGroupSymbols.contains(ch)) {
|
||||
} else if (MathEntityType.openGroupSymbols.contains(s.charAt(result))) {
|
||||
numberOfOpenGroups--;
|
||||
} else {
|
||||
if (stop(s, numberOfOpenGroups, result)) break;
|
||||
@ -90,12 +131,12 @@ public class ToJsclPreprocessor implements Preprocessor {
|
||||
}
|
||||
|
||||
private boolean stop(String s, int numberOfOpenGroups, int i) {
|
||||
if ( numberOfOpenGroups == 0 ) {
|
||||
if (numberOfOpenGroups == 0) {
|
||||
if (i > 0) {
|
||||
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
|
||||
endsWithFinder.setI(i+1);
|
||||
if ( !CollectionsUtils.contains(MathEntityType.prefixFunctions, FilterType.included, endsWithFinder) ) {
|
||||
MathEntityType type = MathEntityType.getType(s.charAt(i));
|
||||
endsWithFinder.setI(i + 1);
|
||||
if (!CollectionsUtils.contains(MathEntityType.prefixFunctions, FilterType.included, endsWithFinder)) {
|
||||
MathEntityType type = MathEntityType.getType(s, i);
|
||||
if (type != null && type != MathEntityType.constant) {
|
||||
return true;
|
||||
}
|
||||
@ -123,27 +164,6 @@ public class ToJsclPreprocessor implements Preprocessor {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class StartsWithFinder implements Finder<String> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final String targetString;
|
||||
|
||||
private StartsWithFinder(@NotNull String targetString) {
|
||||
this.targetString = targetString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFound(@Nullable String s) {
|
||||
return targetString.startsWith(s, i);
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EndsWithFinder implements Finder<String> {
|
||||
|
||||
private int i;
|
||||
@ -165,25 +185,25 @@ public class ToJsclPreprocessor implements Preprocessor {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkMultiplicationSignBeforeFunction(@NotNull StringBuilder sb, @NotNull String s, int i) {
|
||||
private static void checkMultiplicationSignBeforeFunction(@NotNull StringBuilder sb, @NotNull String s, int i, boolean constantBefore) {
|
||||
if (i > 0) {
|
||||
// get character before function
|
||||
char chBefore = s.charAt(i - 1);
|
||||
char ch = s.charAt(i);
|
||||
|
||||
final MathEntityType mathTypeBefore = MathEntityType.getType(String.valueOf(chBefore));
|
||||
final MathEntityType mathType = MathEntityType.getType(String.valueOf(ch));
|
||||
final MathEntityType mathType = MathEntityType.getType(s, i);
|
||||
|
||||
if (mathTypeBefore != MathEntityType.binary_operation &&
|
||||
if (constantBefore || (mathTypeBefore != MathEntityType.binary_operation &&
|
||||
mathTypeBefore != MathEntityType.unary_operation &&
|
||||
mathTypeBefore != MathEntityType.function &&
|
||||
!MathEntityType.openGroupSymbols.contains(chBefore)) {
|
||||
mathTypeBefore != MathEntityType.function &&
|
||||
!MathEntityType.openGroupSymbols.contains(chBefore))) {
|
||||
|
||||
if (mathType == MathEntityType.constant) {
|
||||
sb.append("*");
|
||||
} else if (MathEntityType.openGroupSymbols.contains(ch) && mathTypeBefore != null) {
|
||||
sb.append("*");
|
||||
} else if (mathType == MathEntityType.digit && mathTypeBefore != MathEntityType.digit && mathTypeBefore != MathEntityType.dot) {
|
||||
} else if (mathType == MathEntityType.digit && ((mathTypeBefore != MathEntityType.digit && mathTypeBefore != MathEntityType.dot) || constantBefore) ) {
|
||||
sb.append("*");
|
||||
} else {
|
||||
for (String function : MathEntityType.prefixFunctions) {
|
||||
|
@ -13,6 +13,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.simpleframework.xml.Serializer;
|
||||
import org.simpleframework.xml.core.Persister;
|
||||
import org.solovyev.android.calculator.math.MathEntityComparator;
|
||||
import org.solovyev.android.calculator.math.MathEntityType;
|
||||
import org.solovyev.common.utils.CollectionsUtils;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
@ -46,20 +47,34 @@ public class VarsRegister {
|
||||
public Var addVar(@Nullable String name, @NotNull Var.Builder builder) {
|
||||
final Var var = builder.create();
|
||||
|
||||
final Var varFromRegister = getVar(name == null ? var.getName() : name);
|
||||
Var varFromRegister = getVar(name == null ? var.getName() : name);
|
||||
if (varFromRegister == null) {
|
||||
varFromRegister = var;
|
||||
vars.add(var);
|
||||
} else {
|
||||
varFromRegister.copy(var);
|
||||
}
|
||||
|
||||
return var;
|
||||
return varFromRegister;
|
||||
}
|
||||
|
||||
public void remove (@NotNull Var var) {
|
||||
this.vars.remove(var);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getVarNames () {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
|
||||
for (Var var : vars) {
|
||||
result.add(var.getName());
|
||||
}
|
||||
|
||||
Collections.sort(result, new MathEntityComparator());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Var getVar(@NotNull final String name) {
|
||||
return CollectionsUtils.get(vars, new Finder<Var>() {
|
||||
@ -121,7 +136,7 @@ public class VarsRegister {
|
||||
} else if (systemVarName.equals("π")) {
|
||||
systemVar = new Var.Builder(systemVarName, Math.PI).setSystem(true).create();
|
||||
} else if (systemVarName.equals("i")) {
|
||||
systemVar = new Var.Builder(systemVarName, "√(-1)").setSystem(true).create();
|
||||
systemVar = new Var.Builder(systemVarName, "sqrt(-1)").setSystem(true).create();
|
||||
} else {
|
||||
throw new IllegalArgumentException(systemVarName + " is not supported yet!");
|
||||
}
|
||||
@ -157,7 +172,7 @@ public class VarsRegister {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
editor.putString(context.getString(R.string.p_calc_vars),sw.toString());
|
||||
editor.putString(context.getString(R.string.p_calc_vars), sw.toString());
|
||||
|
||||
editor.commit();
|
||||
}
|
||||
|
@ -5,41 +5,48 @@
|
||||
|
||||
package org.solovyev.android.calculator.math;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/17/11
|
||||
* Time: 10:01 PM
|
||||
*/
|
||||
public interface Functions {
|
||||
public class Functions {
|
||||
|
||||
String SIN = "sin";
|
||||
String SINH = "sinh";
|
||||
String ASIN = "asin";
|
||||
String ASINH = "asinh";
|
||||
String COS = "cos";
|
||||
String COSH = "cosh";
|
||||
String ACOS = "acos";
|
||||
String ACOSH = "acosh";
|
||||
String TAN = "tan";
|
||||
String TANH = "tanh";
|
||||
String ATAN = "atan";
|
||||
String ATANH = "atanh";
|
||||
String LOG = "log";
|
||||
String LN = "ln";
|
||||
String MOD = "mod";
|
||||
String EXP = "exp";
|
||||
String SQRT_SIGN = "√";
|
||||
String SQRT = "sqrt";
|
||||
public final static String SIN = "sin";
|
||||
public final static String SINH = "sinh";
|
||||
public final static String ASIN = "asin";
|
||||
public final static String ASINH = "asinh";
|
||||
public final static String COS = "cos";
|
||||
public final static String COSH = "cosh";
|
||||
public final static String ACOS = "acos";
|
||||
public final static String ACOSH = "acosh";
|
||||
public final static String TAN = "tan";
|
||||
public final static String TANH = "tanh";
|
||||
public final static String ATAN = "atan";
|
||||
public final static String ATANH = "atanh";
|
||||
public final static String LOG = "log";
|
||||
public final static String LN = "ln";
|
||||
public final static String MOD = "mod";
|
||||
public final static String EXP = "exp";
|
||||
public final static String SQRT_SIGN = "√";
|
||||
public final static String SQRT = "sqrt";
|
||||
|
||||
public static final List<String> allPrefix = Arrays.asList(SIN, SINH, ASIN, ASINH, COS, COSH, ACOS, ACOSH, TAN, TANH, ATAN, ATANH, LOG, LN, MOD, SQRT, SQRT_SIGN, EXP);
|
||||
public static final List<String> allPrefix;
|
||||
|
||||
Character FACT = '!';
|
||||
Character DEGREE = '°';
|
||||
static {
|
||||
final List<String> functions = new ArrayList<String>(Arrays.asList(SIN, SINH, ASIN, ASINH, COS, COSH, ACOS, ACOSH, TAN, TANH, ATAN, ATANH, LOG, LN, MOD, SQRT, SQRT_SIGN, EXP));
|
||||
Collections.sort(functions, new MathEntityComparator());
|
||||
allPrefix = functions;
|
||||
}
|
||||
|
||||
public final static Character FACT = '!';
|
||||
public final static Character DEGREE = '°';
|
||||
|
||||
public static final List<Character> allPostfix = Arrays.asList(FACT, DEGREE);
|
||||
|
||||
private Functions() {
|
||||
throw new AssertionError("Not allowed!");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
* or visit http://se.solovyev.org
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.math;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/3/11
|
||||
* Time: 12:30 AM
|
||||
*/
|
||||
public class MathEntityComparator implements Comparator<String> {
|
||||
|
||||
@Override
|
||||
public int compare(String s, String s1) {
|
||||
return s1.length() - s.length();
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ package org.solovyev.android.calculator.math;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorModel;
|
||||
import org.solovyev.android.calculator.CharacterAtPositionFinder;
|
||||
import org.solovyev.android.calculator.StartsWithFinder;
|
||||
import org.solovyev.android.calculator.Var;
|
||||
import org.solovyev.common.utils.CollectionsUtils;
|
||||
import org.solovyev.common.utils.Finder;
|
||||
@ -31,11 +33,12 @@ public enum MathEntityType {
|
||||
|
||||
public static final List<String> constants = Arrays.asList("e", "π", "i");
|
||||
|
||||
public static final List<String> digits = Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
|
||||
public static final List<Character> dots = Arrays.asList('.');
|
||||
|
||||
public static final List<Character> unaryOperations = Arrays.asList('-', '=', '!');
|
||||
|
||||
public static final List<Character> binaryOperations = Arrays.asList('-', '+', '*', '×', '∙', '/', '^' );
|
||||
public static final List<Character> binaryOperations = Arrays.asList('-', '+', '*', '×', '∙', '/', '^');
|
||||
|
||||
public static final List<String> prefixFunctions = Functions.allPrefix;
|
||||
|
||||
@ -48,6 +51,7 @@ public enum MathEntityType {
|
||||
public static final List<Character> closeGroupSymbols = Arrays.asList(']', ')', '}');
|
||||
|
||||
public static final List<Character> singleGroupSymbols;
|
||||
|
||||
static {
|
||||
final List<Character> list = new ArrayList<Character>();
|
||||
list.addAll(openGroupSymbols);
|
||||
@ -56,19 +60,19 @@ public enum MathEntityType {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static MathEntityType getType( @NotNull String s ) {
|
||||
public static MathEntityType getType(@NotNull String s) {
|
||||
MathEntityType result = null;
|
||||
|
||||
if ( s.length() == 1 ) {
|
||||
if (s.length() == 1) {
|
||||
result = getType(s.charAt(0));
|
||||
}
|
||||
|
||||
if ( result == null ) {
|
||||
if ( isConstant(s) ) {
|
||||
result = MathEntityType.constant;
|
||||
} else if ( prefixFunctions.contains(s) ) {
|
||||
if (result == null) {
|
||||
if (prefixFunctions.contains(s)) {
|
||||
result = MathEntityType.function;
|
||||
} else if ( groupSymbols.contains(s) ) {
|
||||
} else if (isConstant(s)) {
|
||||
result = MathEntityType.constant;
|
||||
} else if (groupSymbols.contains(s)) {
|
||||
result = MathEntityType.group_symbols;
|
||||
}
|
||||
}
|
||||
@ -81,19 +85,19 @@ public enum MathEntityType {
|
||||
public static MathEntityType getType(final char ch) {
|
||||
MathEntityType result = null;
|
||||
|
||||
if ( Character.isDigit(ch) ) {
|
||||
if (Character.isDigit(ch)) {
|
||||
result = MathEntityType.digit;
|
||||
} else if ( postfixFunctions.contains(ch) ) {
|
||||
} else if (postfixFunctions.contains(ch)) {
|
||||
result = MathEntityType.postfix_function;
|
||||
} else if ( unaryOperations.contains(ch) ) {
|
||||
} else if (unaryOperations.contains(ch)) {
|
||||
result = MathEntityType.unary_operation;
|
||||
} else if ( binaryOperations.contains(ch) ) {
|
||||
} else if (binaryOperations.contains(ch)) {
|
||||
result = MathEntityType.binary_operation;
|
||||
} else if ( singleGroupSymbols.contains(ch) ) {
|
||||
} else if (singleGroupSymbols.contains(ch)) {
|
||||
result = MathEntityType.group_symbol;
|
||||
} else if (isConstant(ch)) {
|
||||
result = MathEntityType.constant;
|
||||
} else if ( dots.contains(ch) ) {
|
||||
} else if (dots.contains(ch)) {
|
||||
result = MathEntityType.dot;
|
||||
}
|
||||
return result;
|
||||
@ -113,4 +117,46 @@ public enum MathEntityType {
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
|
||||
public static MathEntityType getType(String s, int i) {
|
||||
final StartsWithFinder startsWithFinder = new StartsWithFinder(s, i);
|
||||
final CharacterAtPositionFinder characterStartWithFinder = new CharacterAtPositionFinder(s, i);
|
||||
|
||||
return getType(startsWithFinder, characterStartWithFinder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static MathEntityType getType(@NotNull Finder<String> finder, @NotNull CharacterAtPositionFinder characterStartWithFinder) {
|
||||
MathEntityType result = null;
|
||||
|
||||
if (contains(digits, finder)) {
|
||||
result = MathEntityType.digit;
|
||||
} else if (contains(postfixFunctions, characterStartWithFinder)) {
|
||||
result = MathEntityType.postfix_function;
|
||||
} else if (contains(unaryOperations, characterStartWithFinder)) {
|
||||
result = MathEntityType.unary_operation;
|
||||
} else if (contains(binaryOperations, characterStartWithFinder)) {
|
||||
result = MathEntityType.binary_operation;
|
||||
} else if (contains(groupSymbols, finder)) {
|
||||
result = MathEntityType.group_symbols;
|
||||
} else if (contains(singleGroupSymbols, characterStartWithFinder)) {
|
||||
result = MathEntityType.group_symbol;
|
||||
} else if (contains(prefixFunctions, finder)) {
|
||||
result = MathEntityType.function;
|
||||
} else if (contains(CalculatorModel.getInstance().getVarsRegister().getVarNames(), finder)) {
|
||||
result = MathEntityType.constant;
|
||||
} else if (contains(dots, characterStartWithFinder)) {
|
||||
result = MathEntityType.dot;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean contains(@NotNull List<String> list, @NotNull final Finder<String> startsWithFinder) {
|
||||
return CollectionsUtils.get(list, startsWithFinder) != null;
|
||||
}
|
||||
|
||||
private static boolean contains(@NotNull List<Character> list, @NotNull final CharacterAtPositionFinder atPositionFinder) {
|
||||
return CollectionsUtils.get(list, atPositionFinder) != null;
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import bsh.EvalError;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -47,6 +47,25 @@ public class CalculatorModelTest {
|
||||
Assert.assertEquals("-3.41007+3.41007i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)"));
|
||||
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)"));
|
||||
|
||||
CalculatorModel.getInstance().getVarsRegister().addVar(null, new Var.Builder("si", 5d));
|
||||
Assert.assertEquals("5.0", cm.evaluate(JsclOperation.numeric, "si"));
|
||||
try {
|
||||
cm.evaluate(JsclOperation.numeric, "sin");
|
||||
Assert.fail();
|
||||
} catch (EvalError e) {
|
||||
}
|
||||
Assert.assertEquals("-0.95892", cm.evaluate(JsclOperation.numeric, "sin(5)"));
|
||||
Assert.assertEquals("-4.79462", cm.evaluate(JsclOperation.numeric, "sin(5)si"));
|
||||
Assert.assertEquals("-23.97311", cm.evaluate(JsclOperation.numeric, "sisin(5)si"));
|
||||
Assert.assertEquals("-23.97311", cm.evaluate(JsclOperation.numeric, "si*sin(5)si"));
|
||||
Assert.assertEquals("-3.30879", cm.evaluate(JsclOperation.numeric, "sisin(5si)si"));
|
||||
|
||||
CalculatorModel.getInstance().getVarsRegister().addVar(null, new Var.Builder("s", 1d));
|
||||
Assert.assertEquals("5.0", cm.evaluate(JsclOperation.numeric, "si"));
|
||||
|
||||
CalculatorModel.getInstance().getVarsRegister().addVar(null, new Var.Builder("k", 3.5d));
|
||||
CalculatorModel.getInstance().getVarsRegister().addVar(null, new Var.Builder("k1", 4d));
|
||||
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "k11"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user