rounding fix + color display + refactor

This commit is contained in:
serso 2011-10-21 00:29:55 +04:00
parent 2753f3f53d
commit c554cfc9f3
10 changed files with 300 additions and 231 deletions

View File

@ -6,8 +6,14 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.graphics.Color;
import android.text.Html;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor;
/**
* User: serso
@ -18,6 +24,9 @@ public class CalculatorDisplay extends TextView {
private boolean valid = true;
@NotNull
private final static TextProcessor<String> textHighlighter = new TextHighlighter(Color.WHITE);
public CalculatorDisplay(Context context) {
super(context);
}
@ -44,4 +53,22 @@ public class CalculatorDisplay extends TextView {
setValid(true);
}
public synchronized void redraw() {
if (isValid()) {
String text = getText().toString();
Log.d(this.getClass().getName(), text);
try {
text = textHighlighter.process(text);
} catch (ParseException e) {
Log.e(this.getClass().getName(), e.getMessage(), e);
}
Log.d(this.getClass().getName(), text);
super.setText(Html.fromHtml(text), BufferType.EDITABLE);
}
}
}

View File

@ -171,19 +171,20 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
}
private void evaluate(@Nullable final String expression) {
final CalculatorDisplay localDisplay = display;
if (!StringUtils.isEmpty(expression)) {
try {
Log.d(CalculatorModel.class.getName(), "Trying to evaluate: " + expression /*+ StringUtils.fromStackTrace(Thread.currentThread().getStackTrace())*/);
localDisplay.setText(calculatorEngine.evaluate(JsclOperation.numeric, expression));
display.setText(calculatorEngine.evaluate(JsclOperation.numeric, expression));
} catch (EvalError e) {
handleEvaluationException(expression, localDisplay, e);
handleEvaluationException(expression, display, e);
} catch (ParseException e) {
handleEvaluationException(expression, localDisplay, e);
handleEvaluationException(expression, display, e);
}
} else {
localDisplay.setText("");
this.display.setText("");
}
this.display.redraw();
}
private void handleEvaluationException(@NotNull String expression, @NotNull CalculatorDisplay localDisplay, @NotNull Exception e) {
@ -212,15 +213,19 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
final MathType.Result mathType = MathType.getType(text, 0);
int cursorPositionOffset = 0;
final StringBuilder textToBeInserted = new StringBuilder(text);
switch (mathType.getMathType()) {
case function:
textToBeInserted.append("()");
cursorPositionOffset = -1;
break;
case group_symbols:
}
if (cursorPositionOffset == 0) {
if ( MathType.openGroupSymbols.contains(text) ) {
cursorPositionOffset = -1;
break;
}
}
editor.getText().insert(editor.getSelectionStart(), textToBeInserted.toString());
@ -256,6 +261,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
setValuesFromHistory(this.display, editorHistoryState.getDisplayState());
editor.redraw();
display.redraw();
}
}

View File

@ -97,15 +97,15 @@ public class TextHighlighter implements TextProcessor<String> {
for (; i < s.length(); i++) {
char ch = s.charAt(i);
if (MathType.openGroupSymbols.contains(ch)) {
if (MathType.open_group_symbol.getTokens().contains(String.valueOf(ch))) {
result.append(ch);
result.append("</font>");
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
if (i < s.length() && MathType.closeGroupSymbols.contains(s.charAt(i))) {
if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) {
result.append(s.charAt(i));
}
} else if (MathType.closeGroupSymbols.contains(ch)) {
} else if (MathType.close_group_symbol.getTokens().contains(String.valueOf(ch))) {
break;
} else {
result.append(ch);

View File

@ -7,12 +7,14 @@
package org.solovyev.android.calculator.jscl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor;
import org.solovyev.common.utils.MathUtils;
import org.solovyev.util.math.Complex;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* User: serso
@ -25,11 +27,12 @@ class FromJsclNumericTextProcessor implements TextProcessor<String> {
@Override
public String process(@NotNull String result) throws ParseException {
try {
final Double roundedValue = round(result);
if ( roundedValue.isInfinite() ) {
final Double doubleValue = Double.valueOf(result);
if (doubleValue.isInfinite()) {
result = MathType.INFINITY;
} else {
result = String.valueOf(roundedValue);
result = format(doubleValue);
}
} catch (NumberFormatException e) {
result = result.replace(MathType.INFINITY_JSCL, MathType.INFINITY);
@ -49,6 +52,21 @@ class FromJsclNumericTextProcessor implements TextProcessor<String> {
return result;
}
private String format(@NotNull String value) {
return format(Double.valueOf(value));
}
private String format(@NotNull Double value) {
if (!value.isInfinite() && !value.isNaN()) {
final DecimalFormat df = new DecimalFormat();
df.setGroupingUsed(false);
df.setMaximumFractionDigits(CalculatorEngine.instance.getPrecision());
return df.format(new BigDecimal(value).setScale(CalculatorEngine.instance.getPrecision(), BigDecimal.ROUND_HALF_UP).doubleValue());
} else {
return String.valueOf(value);
}
}
protected String createResultForComplexNumber(@NotNull final String s) {
final Complex complex = new Complex();
@ -56,13 +74,13 @@ class FromJsclNumericTextProcessor implements TextProcessor<String> {
// may be it's just complex number
int plusIndex = s.lastIndexOf("+");
if (plusIndex >= 0) {
complex.setReal(round(s.substring(0, plusIndex)));
complex.setReal(format(s.substring(0, plusIndex)));
result += complex.getReal();
result += "+";
} else {
plusIndex = s.lastIndexOf("-");
if (plusIndex >= 0) {
complex.setReal(round(s.substring(0, plusIndex)));
complex.setReal(format(s.substring(0, plusIndex)));
result += complex.getReal();
result += "-";
}
@ -71,7 +89,7 @@ class FromJsclNumericTextProcessor implements TextProcessor<String> {
int multiplyIndex = s.indexOf("*");
if (multiplyIndex >= 0) {
complex.setImaginary(round(s.substring(plusIndex >= 0 ? plusIndex + 1 : 0, multiplyIndex)));
complex.setImaginary(format(s.substring(plusIndex >= 0 ? plusIndex + 1 : 0, multiplyIndex)));
result += complex.getImaginary();
}
@ -81,8 +99,31 @@ class FromJsclNumericTextProcessor implements TextProcessor<String> {
return result;
}
private Double round(@NotNull String result) {
final Double dResult = Double.valueOf(result);
return MathUtils.round(dResult, CalculatorEngine.instance.getNumberOfFractionDigits());
private class Complex {
@Nullable
private String real;
@Nullable
private String imaginary;
@Nullable
public String getReal() {
return real;
}
public void setReal(@Nullable String real) {
this.real = real;
}
@Nullable
public String getImaginary() {
return imaginary;
}
public void setImaginary(@Nullable String imaginary) {
this.imaginary = imaginary;
}
}
}

View File

@ -49,8 +49,8 @@ public class Functions {
allPrefix = functions;
}
public final static Character FACT = '!';
public final static Character DEGREE = '°';
public final static String FACT = "!";
public final static String DEGREE = "°";
public static final List<Character> allPostfix = Arrays.asList(FACT, DEGREE);
public static final List<String> allPostfix = Arrays.asList(FACT, DEGREE);
}

View File

@ -9,60 +9,119 @@ import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CharacterAtPositionFinder;
import org.solovyev.android.calculator.StartsWithFinder;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.Finder;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import static org.solovyev.common.utils.CollectionsUtils.get;
public enum MathType {
digit,
dot,
power_10,
constant,
function,
postfix_function,
unary_operation,
binary_operation,
group_symbols,
open_group_symbol,
close_group_symbol,
text;
digit(100, true, true, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9") {
@Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit && mathTypeBefore != dot;
}
},
dot(200, true, true, "."){
@Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
}
},
power_10(300, true, false, "E"),
postfix_function(400, true, false, Functions.allPostfix),
unary_operation(500, false, false, "-", "=", "!"),
binary_operation(600, false, false, "-", "+", "*", "×", "", "/", "^"),
open_group_symbol(800, true, false, "[", "(", "{") {
@Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function;
}
},
close_group_symbol(900, false, true, "]", ")", "}") {
@Override
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return false;
}
},
function(1000, true, true, Functions.allPrefix),
constant(1100, true, true) {
@NotNull
@Override
public List<String> getTokens() {
return CalculatorEngine.instance.getVarsRegister().getVarNames();
}
},
text(1200, false, false);
@NotNull
private final List<String> tokens;
@NotNull
private final Integer priority;
private final boolean needMultiplicationSignBefore;
private final boolean needMultiplicationSignAfter;
MathType(@NotNull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@NotNull String... tokens) {
this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, CollectionsUtils.asList(tokens));
}
MathType(@NotNull Integer priority,
boolean needMultiplicationSignBefore,
boolean needMultiplicationSignAfter,
@NotNull List<String> tokens) {
this.priority = priority;
this.needMultiplicationSignBefore = needMultiplicationSignBefore;
this.needMultiplicationSignAfter = needMultiplicationSignAfter;
this.tokens = Collections.unmodifiableList(tokens);
}
@NotNull
public List<String> getTokens() {
return tokens;
}
private boolean isNeedMultiplicationSignBefore() {
return needMultiplicationSignBefore;
}
private boolean isNeedMultiplicationSignAfter() {
return needMultiplicationSignAfter;
}
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
}
public static final List<String> openGroupSymbols = Arrays.asList("[]", "()", "{}");
public final static Character POWER_10 = 'E';
public final static String POWER_10_JSCL = "10^";
public static final String IMAGINARY_NUMBER = "i";
public static final String IMAGINARY_NUMBER_JSCL = "sqrt(-1)";
public static final String PI = "π";
public static final String E = "e";
public final static String NAN = "NaN";
public final static String INFINITY = "";
public final static String INFINITY_JSCL = "Infinity";
public static final List<String> constants = Arrays.asList(E, PI, IMAGINARY_NUMBER, NAN, INFINITY);
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<String> prefixFunctions = Functions.allPrefix;
public static final List<Character> postfixFunctions = Functions.allPostfix;
public static final List<String> groupSymbols = Arrays.asList("[]", "()", "{}");
public static final List<Character> openGroupSymbols = Arrays.asList('[', '(', '{');
public static final List<Character> closeGroupSymbols = Arrays.asList(']', ')', '}');
/**
* Method determines mathematical entity type for text substring starting from ith index
*
@ -80,67 +139,39 @@ public enum MathType {
return new Result(MathType.text, text);
}
final StartsWithFinder stringStartWithFinder = new StartsWithFinder(text, i);
final CharacterAtPositionFinder characterStartWithFinder = new CharacterAtPositionFinder(text, i);
final StartsWithFinder startsWithFinder = new StartsWithFinder(text, i);
String foundString = get(digits, stringStartWithFinder);
if (foundString != null) {
return new Result(MathType.digit, foundString);
for (MathType mathType : getMathTypesByPriority()) {
final String s = get(mathType.getTokens(), startsWithFinder);
if ( s != null ) {
return new Result(mathType, s);
}
Character foundCharacter = get(dots, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(dot, String.valueOf(foundCharacter));
}
foundCharacter = characterStartWithFinder.isFound(POWER_10) ? POWER_10 : null;
if (foundCharacter != null) {
return new Result(power_10, String.valueOf(foundCharacter));
}
foundCharacter = get(postfixFunctions, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(postfix_function, String.valueOf(foundCharacter));
}
foundCharacter = get(unaryOperations, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(unary_operation, String.valueOf(foundCharacter));
}
foundCharacter = get(binaryOperations, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(binary_operation, String.valueOf(foundCharacter));
}
foundString = get(groupSymbols, stringStartWithFinder);
if (foundString != null) {
return new Result(MathType.group_symbols, foundString);
}
foundCharacter = get(openGroupSymbols, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(open_group_symbol, String.valueOf(foundCharacter));
}
foundCharacter = get(closeGroupSymbols, characterStartWithFinder);
if (foundCharacter != null) {
return new Result(close_group_symbol, String.valueOf(foundCharacter));
}
foundString = get(prefixFunctions, stringStartWithFinder);
if (foundString != null) {
return new Result(MathType.function, foundString);
}
foundString = get(CalculatorEngine.instance.getVarsRegister().getVarNames(), stringStartWithFinder);
if (foundString != null) {
return new Result(MathType.constant, foundString);
}
return new Result(MathType.text, text.substring(i));
}
private static List<MathType> mathTypesByPriority;
@NotNull
private static List<MathType> getMathTypesByPriority() {
if ( mathTypesByPriority == null ) {
final List<MathType> result = CollectionsUtils.asList(MathType.values());
Collections.sort(result, new Comparator<MathType>() {
@Override
public int compare(MathType l, MathType r) {
return l.priority.compareTo(r.priority);
}
});
mathTypesByPriority = result;
}
return mathTypesByPriority;
}
public static class Result {
@NotNull
@ -149,7 +180,7 @@ public enum MathType {
@NotNull
private final String match;
public Result(@NotNull MathType mathType, @NotNull String match){
public Result(@NotNull MathType mathType, @NotNull String match) {
this.mathType = mathType;
this.match = match;

View File

@ -39,7 +39,7 @@ public enum CalculatorEngine {
@NotNull
private final Object lock = new Object();
private int numberOfFractionDigits = 5;
private int precision = 5;
@NotNull
public final TextProcessor<PreparedExpression> preprocessor = new ToJsclTextProcessor();
@ -85,12 +85,12 @@ public enum CalculatorEngine {
}
}
public int getNumberOfFractionDigits() {
return numberOfFractionDigits;
public int getPrecision() {
return precision;
}
public void setNumberOfFractionDigits(int numberOfFractionDigits) {
this.numberOfFractionDigits = numberOfFractionDigits;
public void setPrecision(int precision) {
this.precision = precision;
}
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) throws EvalError {
@ -105,7 +105,7 @@ public enum CalculatorEngine {
if (preferences != null) {
final NumberMapper<Integer> integerNumberMapper = new NumberMapper<Integer>(Integer.class);
//noinspection ConstantConditions
this.setNumberOfFractionDigits(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
this.setPrecision(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
}
varsRegister.init(context, preferences);

View File

@ -50,7 +50,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
// NOTE: fix for jscl for EMPTY functions processing (see tests)
startsWithFinder.setI(i + 1);
if ( i < s.length() && CollectionsUtils.get(MathType.groupSymbols, startsWithFinder) != null) {
if ( i < s.length() && CollectionsUtils.get(MathType.openGroupSymbols, startsWithFinder) != null) {
throw new ParseException("Empty function: " + mathTypeResult.getMatch());
/*i += 2;
sb.append("(" + SPECIAL_STRING + ")");
@ -78,7 +78,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
startsWithFinder.setI(i);
int offset = 0;
String functionName = CollectionsUtils.get(MathType.prefixFunctions, startsWithFinder);
String functionName = CollectionsUtils.get(MathType.function.getTokens(), startsWithFinder);
if (functionName == null) {
String varName = CollectionsUtils.get(CalculatorEngine.instance.getVarsRegister().getVarNames(), startsWithFinder);
if (varName != null) {
@ -114,7 +114,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
for (Var var : CalculatorEngine.instance.getVarsRegister().getVars()) {
if (!var.isSystem()) {
if (s.startsWith(var.getName(), i)) {
if (CollectionsUtils.get(MathType.prefixFunctions, startsWithFinder) == null) {
if (CollectionsUtils.get(MathType.function.getTokens(), startsWithFinder) == null) {
}
}
}
@ -149,7 +149,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
if (i > 0) {
final EndsWithFinder endsWithFinder = new EndsWithFinder(s);
endsWithFinder.setI(i + 1);
if (!CollectionsUtils.contains(MathType.prefixFunctions, FilterType.included, endsWithFinder)) {
if (!CollectionsUtils.contains(MathType.function.getTokens(), FilterType.included, endsWithFinder)) {
MathType type = MathType.getType(s, i).getMathType();
if (type != MathType.constant) {
return true;
@ -204,36 +204,16 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
@NotNull String s,
int i,
@Nullable MathType.Result mathTypeBeforeResult) {
MathType.Result result = MathType.getType(s, i);
final MathType.Result result = MathType.getType(s, i);
if (i > 0) {
final MathType mathType = result.getMathType();
final MathType current = result.getMathType();
assert mathTypeBeforeResult != null;
final MathType mathTypeBefore = mathTypeBeforeResult.getMathType();
final MathType before = mathTypeBeforeResult.getMathType();
if (mathTypeBefore == MathType.constant || (mathTypeBefore != MathType.binary_operation &&
mathTypeBefore != MathType.unary_operation &&
mathTypeBefore != MathType.power_10 &&
mathTypeBefore != MathType.function &&
mathTypeBefore != MathType.open_group_symbol)) {
if (mathType == MathType.constant) {
if (current.isNeedMultiplicationSignBefore(before)) {
sb.append("*");
} else if (mathType == MathType.power_10) {
sb.append("*");
} else if (mathType == MathType.open_group_symbol && mathTypeBefore != null) {
sb.append("*");
} else if (mathType == MathType.digit && ((mathTypeBefore != MathType.digit && mathTypeBefore != MathType.dot) || mathTypeBefore == MathType.constant)) {
sb.append("*");
} else {
for (String function : MathType.prefixFunctions) {
if (s.startsWith(function, i)) {
sb.append("*");
break;
}
}
}
}
}

View File

@ -9,7 +9,6 @@ import bsh.EvalError;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.simpleframework.xml.Attribute;
import org.solovyev.android.calculator.jscl.JsclOperation;
/**
@ -28,27 +27,52 @@ public class CalculatorEngineTest {
public void testEvaluate() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "2+2"));
Assert.assertEquals("-0.7568", cm.evaluate(JsclOperation.numeric, "sin(4)"));
Assert.assertEquals("0.5236", cm.evaluate(JsclOperation.numeric, "asin(0.5)"));
Assert.assertEquals("-0.39626", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)"));
Assert.assertEquals("-0.5604", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)sqrt(2)"));
Assert.assertEquals("-0.5604", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)"));
Assert.assertEquals("7.38906", cm.evaluate(JsclOperation.numeric, "e^2"));
Assert.assertEquals("7.38906", cm.evaluate(JsclOperation.numeric, "exp(1)^2"));
Assert.assertEquals("7.38906", cm.evaluate(JsclOperation.numeric, "exp(2)"));
Assert.assertEquals("2.0+i", cm.evaluate(JsclOperation.numeric, "2*1+sqrt(-1)"));
Assert.assertEquals("0.92054+3.14159i", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))"));
Assert.assertEquals("7.38906i", cm.evaluate(JsclOperation.numeric, "iexp(2)"));
Assert.assertEquals("2.0+7.38906i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)"));
Assert.assertEquals("2.0+7.38906i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)"));
Assert.assertEquals("2.0-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i"));
Assert.assertEquals("-2.0-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i"));
Assert.assertEquals("-2.0+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i"));
Assert.assertEquals("-2.0+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i"));
Assert.assertEquals("-3.41007+3.41007i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)"));
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "2+2"));
Assert.assertEquals("-0.757", cm.evaluate(JsclOperation.numeric, "sin(4)"));
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "asin(0.5)"));
Assert.assertEquals("-0.396", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)"));
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)sqrt(2)"));
Assert.assertEquals("-0.56", cm.evaluate(JsclOperation.numeric, "sin(4)asin(0.5)√(2)"));
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "e^2"));
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(1)^2"));
Assert.assertEquals("7.389", cm.evaluate(JsclOperation.numeric, "exp(2)"));
Assert.assertEquals("2+i", cm.evaluate(JsclOperation.numeric, "2*1+sqrt(-1)"));
Assert.assertEquals("0.921+3.142i", cm.evaluate(JsclOperation.numeric, "ln(5cosh(38π√(2cos(2))))"));
Assert.assertEquals("7.389i", cm.evaluate(JsclOperation.numeric, "iexp(2)"));
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+iexp(2)"));
Assert.assertEquals("2+7.389i", cm.evaluate(JsclOperation.numeric, "2+√(-1)exp(2)"));
Assert.assertEquals("2-2.5i", cm.evaluate(JsclOperation.numeric, "2-2.5i"));
Assert.assertEquals("-2-2.5i", cm.evaluate(JsclOperation.numeric, "-2-2.5i"));
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i"));
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i"));
Assert.assertEquals("-3.41+3.41i", cm.evaluate(JsclOperation.numeric, "(5tan(2i)+2i)/(1-i)"));
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("si", 5d));
Assert.assertEquals("-0.959", cm.evaluate(JsclOperation.numeric, "sin(5)"));
Assert.assertEquals("-4.795", cm.evaluate(JsclOperation.numeric, "sin(5)si"));
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "sisin(5)si"));
Assert.assertEquals("-23.973", cm.evaluate(JsclOperation.numeric, "si*sin(5)si"));
Assert.assertEquals("-3.309", cm.evaluate(JsclOperation.numeric, "sisin(5si)si"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("s", 1d));
Assert.assertEquals("5", cm.evaluate(JsclOperation.numeric, "si"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k", 3.5d));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k1", 4d));
Assert.assertEquals("4", cm.evaluate(JsclOperation.numeric, "k11"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("t", (String)null));
Assert.assertEquals("11×t", cm.evaluate(JsclOperation.numeric, "t11"));
Assert.assertEquals("11×e×t", cm.evaluate(JsclOperation.numeric, "t11e"));
Assert.assertEquals("11×Infinity×t", cm.evaluate(JsclOperation.numeric, "t11∞"));
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)"));
}
@Test
public void testEmptyFunction() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
try {
cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos(cos(cos(cos(cos(acos(acos(acos(acos(acos(acos(acos(acos(cos(cos(cos(cos(cosh(acos(cos())))))))))))))))))))))))))))))))))))))");
Assert.fail();
@ -60,78 +84,28 @@ public class CalculatorEngineTest {
Assert.fail();
} catch (ParseException e){
}
Assert.assertEquals("0.73909", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))"));
Assert.assertEquals("0.739", cm.evaluate(JsclOperation.numeric, "cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(1))))))))))))))))))))))))))))))))))))"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("si", 5d));
Assert.assertEquals("5.0", cm.evaluate(JsclOperation.numeric, "si"));
Assert.assertEquals("5", 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"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("s", 1d));
Assert.assertEquals("5.0", cm.evaluate(JsclOperation.numeric, "si"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k", 3.5d));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("k1", 4d));
Assert.assertEquals("4.0", cm.evaluate(JsclOperation.numeric, "k11"));
CalculatorEngine.instance.getVarsRegister().addVar(null, new Var.Builder("t", (String)null));
Assert.assertEquals("11*t", cm.evaluate(JsclOperation.numeric, "t11"));
Assert.assertEquals("11*2.718281828459045*t", cm.evaluate(JsclOperation.numeric, "t11e"));
Assert.assertEquals("11*Infinity*t", cm.evaluate(JsclOperation.numeric, "t11∞"));
Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)"));
}
public interface TestInterface {
Integer getField();
}
@Test
public void testRounding() throws Exception {
final CalculatorEngine cm = CalculatorEngine.instance;
public class TestClass implements TestInterface{
cm.setPrecision(2);
Assert.assertEquals("12345678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7"));
cm.setPrecision(10);
Assert.assertEquals("12345678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7"));
Assert.assertEquals("123456789", cm.evaluate(JsclOperation.numeric, "1.234567890E8"));
Assert.assertEquals("1234567890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9"));
@Attribute(required = true)
private Integer field;
public TestClass() {
}
public TestClass(Integer field) {
this.field = field;
}
public Integer getField() {
return field;
}
public void setField(Integer field) {
this.field = field;
}
}
public class NewTestClass implements TestInterface{
@Attribute
private Integer field;
public NewTestClass() {
}
public NewTestClass(Integer field) {
this.field = field;
}
public Integer getField() {
return field;
}
public void setField(Integer field) {
this.field = field;
}
}
}

View File

@ -9,7 +9,6 @@ package org.solovyev.android.calculator.model;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.solovyev.android.calculator.jscl.JsclOperation;
/**
* User: serso
@ -27,6 +26,17 @@ public class ToJsclTextProcessorTest {
public void testProcess() throws Exception {
final ToJsclTextProcessor preprocessor = new ToJsclTextProcessor();
Assert.assertEquals( "", preprocessor.process("").toString());
Assert.assertEquals( "()", preprocessor.process("[]").toString());
Assert.assertEquals( "()*()", preprocessor.process("[][]").toString());
Assert.assertEquals( "()*(1)", preprocessor.process("[][1]").toString());
Assert.assertEquals( "(0)*(1)", preprocessor.process("[0][1]").toString());
Assert.assertEquals( "(0)*(1*10^)", preprocessor.process("[0][1E]").toString());
Assert.assertEquals( "(0)*(1*10^1)", preprocessor.process("[0][1E1]").toString());
Assert.assertEquals( "(0)*(1*10^-1)", preprocessor.process("[0][1E-1]").toString());
Assert.assertEquals( "(0)*(1.*10^-1)", preprocessor.process("[0][1.E-1]").toString());
Assert.assertEquals( "(0)*(2*10^-1)", preprocessor.process("[0][2*E-1]").toString());
Assert.assertEquals( "(0)*log(1)*(2*10^-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString());
Assert.assertEquals( "sin(4)*asin(0.5)*sqrt(2)", preprocessor.process("sin(4)asin(0.5)sqrt(2)").toString());
Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString());
Assert.assertEquals( "3.141592653589793*sin(4)*3.141592653589793*cos(sqrt(5))", preprocessor.process("πsin(4)πcos(√(5))").toString());