From 567551d95269cf3de0b34c0835c633987824a523 Mon Sep 17 00:00:00 2001 From: Sergey Solovyev Date: Thu, 15 Dec 2011 15:56:32 +0400 Subject: [PATCH] number formatting + fixes --- .../android/calculator/CalculatorDisplay.java | 2 +- .../android/calculator/CalculatorEditor.java | 2 +- .../android/calculator/TextHighlighter.java | 13 +- .../android/calculator/math/MathType.java | 52 ++-- .../calculator/model/CalculatorEngine.java | 5 +- .../model/CalculatorEvalException.java | 4 +- .../model/FromJsclSimplifyTextProcessor.java | 8 +- .../calculator/model/NumberBuilder.java | 254 +++++++++++------- .../calculator/model/ToJsclTextProcessor.java | 3 +- .../calculator/TextHighlighterTest.java | 6 +- .../model/CalculatorEngineTest.java | 12 + 11 files changed, 222 insertions(+), 139 deletions(-) diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java b/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java index 325a3114..32566ee5 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorDisplay.java @@ -35,7 +35,7 @@ public class CalculatorDisplay extends AutoResizeTextView { private JsclOperation jsclOperation = JsclOperation.numeric; @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine()); + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); @Nullable private Generic genericResult; diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java index 56f1fa81..a6e9c328 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorEditor.java @@ -31,7 +31,7 @@ public class CalculatorEditor extends EditText implements SharedPreferences.OnSh private boolean highlightText = true; @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine()); public CalculatorEditor(Context context) { super(context); diff --git a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java index 2b1d9b79..fda75b89 100644 --- a/src/main/java/org/solovyev/android/calculator/TextHighlighter.java +++ b/src/main/java/org/solovyev/android/calculator/TextHighlighter.java @@ -10,8 +10,9 @@ import jscl.MathContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.math.MathType; -import org.solovyev.android.calculator.model.NumberBuilder; +import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorParseException; +import org.solovyev.android.calculator.model.NumberBuilder; import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.common.utils.MutableObject; @@ -74,11 +75,11 @@ public class TextHighlighter implements TextProcessor> 16) & 0xFF; @@ -100,7 +101,7 @@ public class TextHighlighter implements TextProcessor localNumberOffset = new MutableObject(0); - numberBuilder.process(text1, localNumberOffset); + numberBuilder.processNumber(text1, localNumberOffset); numberOffset += localNumberOffset.getObject(); if (maxNumberOfOpenGroupSymbols > 0) { diff --git a/src/main/java/org/solovyev/android/calculator/math/MathType.java b/src/main/java/org/solovyev/android/calculator/math/MathType.java index 5abf20c8..124b13bf 100644 --- a/src/main/java/org/solovyev/android/calculator/math/MathType.java +++ b/src/main/java/org/solovyev/android/calculator/math/MathType.java @@ -21,7 +21,7 @@ import java.util.*; public enum MathType { - numeral_base(50, true, false) { + numeral_base(50, true, false, MathGroupType.number) { private final List tokens = new ArrayList(10); { @@ -40,23 +40,23 @@ public enum MathType { } }, - dot(200, true, true, ".") { + dot(200, true, true, MathGroupType.number, ".") { @Override public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) { return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit; } }, - grouping_separator(250, false, false, "'", " "){ + grouping_separator(250, false, false, MathGroupType.number, "'", " "){ @Override public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) throws CalculatorParseException { return i; } }, - power_10(300, false, false, "E"), + power_10(300, false, false, MathGroupType.number, "E"), - postfix_function(400, false, true) { + postfix_function(400, false, true, MathGroupType.function) { @NotNull @Override public List getTokens() { @@ -64,8 +64,8 @@ public enum MathType { } }, - unary_operation(500, false, false, "-", "="), - binary_operation(600, false, false, "-", "+", "*", "×", "∙", "/", "^") { + unary_operation(500, false, false, MathGroupType.operation, "-", "="), + binary_operation(600, false, false, MathGroupType.operation, "-", "+", "*", "×", "∙", "/", "^") { @Override protected String getSubstituteToJscl(@NotNull String match) { if (match.equals("×") || match.equals("∙")) { @@ -76,7 +76,7 @@ public enum MathType { } }, - open_group_symbol(800, true, false, "[", "(", "{") { + open_group_symbol(800, true, false, MathGroupType.other, "[", "(", "{") { @Override public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) { return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != function && mathTypeBefore != operator; @@ -88,7 +88,7 @@ public enum MathType { } }, - close_group_symbol(900, false, true, "]", ")", "}") { + close_group_symbol(900, false, true, MathGroupType.other, "]", ")", "}") { @Override public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) { return false; @@ -100,7 +100,7 @@ public enum MathType { } }, - function(1000, true, true) { + function(1000, true, true, MathGroupType.function) { @NotNull @Override public List getTokens() { @@ -108,7 +108,7 @@ public enum MathType { } }, - operator(1050, true, true) { + operator(1050, true, true, MathGroupType.function) { @NotNull @Override public List getTokens() { @@ -116,7 +116,7 @@ public enum MathType { } }, - constant(1100, true, true) { + constant(1100, true, true, MathGroupType.other) { @NotNull @Override public List getTokens() { @@ -129,7 +129,7 @@ public enum MathType { } }, - digit(1125, true, true) { + digit(1125, true, true, MathGroupType.number) { private final List tokens = new ArrayList(16); { @@ -149,9 +149,9 @@ public enum MathType { } }, - comma(1150, false, false, ","), + comma(1150, false, false, MathGroupType.other, ","), - text(1200, false, false) { + text(1200, false, false, MathGroupType.other) { @Override public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) { if (match.length() > 0) { @@ -169,6 +169,13 @@ public enum MathType { } }; + public static enum MathGroupType { + function, + number, + operation, + other + } + @NotNull private final List tokens; @@ -179,24 +186,35 @@ public enum MathType { private final boolean needMultiplicationSignAfter; + @NotNull + private final MathGroupType groupType; + MathType(@NotNull Integer priority, boolean needMultiplicationSignBefore, boolean needMultiplicationSignAfter, + @NotNull MathGroupType groupType, @NotNull String... tokens) { - this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, CollectionsUtils.asList(tokens)); + this(priority, needMultiplicationSignBefore, needMultiplicationSignAfter, groupType, CollectionsUtils.asList(tokens)); } MathType(@NotNull Integer priority, boolean needMultiplicationSignBefore, boolean needMultiplicationSignAfter, + @NotNull MathGroupType groupType, @NotNull List tokens) { this.priority = priority; this.needMultiplicationSignBefore = needMultiplicationSignBefore; this.needMultiplicationSignAfter = needMultiplicationSignAfter; + this.groupType = groupType; this.tokens = Collections.unmodifiableList(tokens); } -/* public static int getPostfixFunctionStart(@NotNull CharSequence s, int position) throws ParseException { + @NotNull + public MathGroupType getGroupType() { + return groupType; + } + + /* public static int getPostfixFunctionStart(@NotNull CharSequence s, int position) throws ParseException { assert s.length() > position; int numberOfOpenGroups = 0; diff --git a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java index e51ceeb5..45e96817 100644 --- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java +++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java @@ -169,7 +169,7 @@ public enum CalculatorEngine { calculationResult.setObject(genericResult); } catch (AbstractJsclArithmeticException e) { - evalException.setObject(new CalculatorEvalException(e, jsclExpression)); + evalException.setObject(new CalculatorEvalException(e, e, jsclExpression)); } catch (ArithmeticException e) { //System.out.println(e.getMessage()); parseException.setObject(new CalculatorParseException(Messages.msg_1, jsclExpression, e.getMessage())); @@ -207,7 +207,8 @@ public enum CalculatorEngine { } if (parseExceptionObject != null || evalExceptionObject != null) { - if (finalOperation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) { + if (finalOperation == JsclOperation.numeric && + ( preparedExpression.isExistsUndefinedVar() || ( evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException)) ) { return evaluate(JsclOperation.simplify, expression, mr); } diff --git a/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java b/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java index 485cac09..5c4e4416 100644 --- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java +++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEvalException.java @@ -6,6 +6,7 @@ package org.solovyev.android.calculator.model; +import jscl.AbstractJsclArithmeticException; import org.jetbrains.annotations.NotNull; import org.solovyev.common.exceptions.SersoException; import org.solovyev.common.msg.Message; @@ -27,7 +28,8 @@ public class CalculatorEvalException extends SersoException implements Message { @NotNull private final String expression; - public CalculatorEvalException(@NotNull Message message, String expression) { + public CalculatorEvalException(@NotNull Message message, @NotNull Throwable cause, String expression) { + super(cause); this.message = message; this.expression = expression; } diff --git a/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java index c163155f..0e45fd31 100644 --- a/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java +++ b/src/main/java/org/solovyev/android/calculator/model/FromJsclSimplifyTextProcessor.java @@ -33,16 +33,16 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor numberOffset) { - number = null; - + public MathType.Result process(@NotNull StringBuilder text, @NotNull MathType.Result mathTypeResult, @Nullable MutableObject offset) { final MathType.Result possibleResult; - if ((CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.numeral_base, MathType.dot, MathType.grouping_separator, MathType.power_10) || - isSignAfterE(mathTypeResult)) && numeralBaseCheck(mathTypeResult) && numeralBaseInTheStart(mathTypeResult.getMathType())) { + if (canContinue(mathTypeResult)) { + // let's continue building number if (numberBuilder == null) { + // if new number => create new builder numberBuilder = new StringBuilder(); } if (mathTypeResult.getMathType() != MathType.numeral_base) { + // just add matching string numberBuilder.append(mathTypeResult.getMatch()); } else { + // set explicitly numeral base (do not include it into number) nb = NumeralBase.getByPrefix(mathTypeResult.getMatch()); } possibleResult = null; } else { - possibleResult = process(sb, numberOffset); + // process current number (and go to the next one) + possibleResult = processNumber(text, offset); } return possibleResult == null ? mathTypeResult : possibleResult; } + /** + * Method determines if we can continue to process current number + * @param mathTypeResult current math type result + * + * @return true if we can continue of processing of current number, if false - new number should be constructed + */ + private boolean canContinue(@NotNull MathType.Result mathTypeResult) { + return ((mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number && numeralBaseCheck(mathTypeResult) && numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult))); + } + private boolean numeralBaseInTheStart(@NotNull MathType mathType) { return mathType != MathType.numeral_base || numberBuilder == null; } - private boolean numeralBaseCheck( @NotNull MathType.Result mathType ) { - if ( mathType.getMathType() == MathType.digit ) { + private boolean numeralBaseCheck(@NotNull MathType.Result mathType) { + if (mathType.getMathType() == MathType.digit) { final Character ch = mathType.getMatch().charAt(0); - if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) && !NumeralBase.dec.getAcceptableCharacters().contains(ch) ) { - if ( nb == NumeralBase.hex ) { + if (NumeralBase.hex.getAcceptableCharacters().contains(ch) && !NumeralBase.dec.getAcceptableCharacters().contains(ch)) { + if (nb == NumeralBase.hex) { return true; } else { return false; @@ -104,101 +125,92 @@ public class NumberBuilder { return false; } - + /** + * Method replaces number in text according to some rules (e.g. formatting) + * + * @param text text where number can be replaced + * @param offset offset between new number length and old number length (newNumberLength - oldNumberLength) + * + * @return new math type result (as one can be changed due to substituting of number with constant) + */ @Nullable - public MathType.Result process(@NotNull StringBuilder sb, @Nullable MutableObject numberOffset) { - int numberOfTokens = 0; + public MathType.Result processNumber(@NotNull StringBuilder text, @Nullable MutableObject offset) { + // total number of trimmed chars + int trimmedChars = 0; + + String number = null; + + // save numeral base (as later it might be replaced) + final NumeralBase localNb = getNumeralBase(); - final NumeralBase localNb; if (numberBuilder != null) { try { number = numberBuilder.toString(); - List tokens = new ArrayList(); + + // let's get rid of unnecessary characters (grouping separators, + after E) + final List tokens = new ArrayList(); tokens.addAll(MathType.grouping_separator.getTokens()); + // + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted ) tokens.add("+"); for (String groupingSeparator : tokens) { - String newNumber = number.replace(groupingSeparator, ""); - numberOfTokens += number.length() - newNumber.length(); - number = newNumber; + final String trimmedNumber = number.replace(groupingSeparator, ""); + trimmedChars += number.length() - trimmedNumber.length(); + number = trimmedNumber; } - - toDouble(number, getNumeralBase()); - + + // check if number still valid + toDouble(number, getNumeralBase(), engine); + } catch (NumberFormatException e) { + // number is not valid => stop number = null; } numberBuilder = null; - localNb = getNumeralBase(); - nb = defaultNumeralBase; - } else { - number = null; - localNb = getNumeralBase(); + + // must set default numeral base (exit numeral base mode) + nb = engine.getNumeralBase(); } - return replaceSystemVars(sb, number, numberOfTokens, numberOffset, localNb, simpleFormat); + return replaceNumberInText(text, number, trimmedChars, offset, localNb, allowScientificFormat, engine); } @Nullable - private static MathType.Result replaceSystemVars(StringBuilder sb, String number, int numberOfTokens, @Nullable MutableObject numberOffset, @NotNull NumeralBase nb, boolean simpleFormat) { + private static MathType.Result replaceNumberInText(@NotNull StringBuilder text, + @Nullable String number, + int trimmedChars, + @Nullable MutableObject offset, + @NotNull NumeralBase nb, + boolean allowScientificFormat, + @NotNull final MathEngine engine) { MathType.Result result = null; if (number != null) { final String finalNumber = number; - final Var var = CollectionsUtils.find(CalculatorEngine.instance.getVarsRegister().getSystemEntities(), new Finder() { + + // detect if current number is precisely equals to constant in constants' registry (NOTE: ONLY FOR SYSTEM CONSTANTS) + final IConstant constant = CollectionsUtils.find(engine.getConstantsRegistry().getSystemEntities(), new Finder() { @Override - public boolean isFound(@Nullable Var var) { - return var != null && finalNumber.equals(var.getValue()); + public boolean isFound(@Nullable IConstant constant) { + return constant != null && finalNumber.equals(constant.getValue()); } }); - if (var != null) { - sb.delete(sb.length() - number.length() - numberOfTokens, sb.length()); - sb.append(var.getName()); - result = new MathType.Result(MathType.constant, var.getName()); + // in any case remove old number from text + final int oldNumberLength = number.length() + trimmedChars; + text.delete(text.length() - oldNumberLength, text.length()); + + if (constant != null) { + // let's change number with constant from registry + text.append(constant.getName()); + result = new MathType.Result(MathType.constant, constant.getName()); } else { - sb.delete(sb.length() - number.length() - numberOfTokens, sb.length()); - - final String formattedNumber; - - if (!simpleFormat) { - int indexOfDot = number.indexOf('.'); - - if (indexOfDot < 0) { - int indexOfE; - if (nb == NumeralBase.hex) { - indexOfE = -1; - } else { - indexOfE = number.indexOf('E'); - } - if (indexOfE < 0) { - formattedNumber = toString(toDouble(number, nb), nb); - } else { - final String part; - if (indexOfDot != 0) { - part = toString(toDouble(number.substring(0, indexOfE), nb), nb); - } else { - part = ""; - } - formattedNumber = part + number.substring(indexOfE); - } - } else { - final String integerPart; - if (indexOfDot != 0) { - integerPart = toString(toDouble(number.substring(0, indexOfDot), nb), nb); - } else { - integerPart = ""; - } - formattedNumber = integerPart + number.substring(indexOfDot); - } - } else { - formattedNumber = toString(toDouble(number, nb), nb); + final String newNumber = formatNumber(number, nb, allowScientificFormat, engine); + if (offset != null) { + // register offset between old number and new number + offset.setObject(newNumber.length() - oldNumberLength); } - - if (numberOffset != null) { - numberOffset.setObject(formattedNumber.length() - number.length() - numberOfTokens); - } - sb.append(formattedNumber); + text.append(newNumber); } } @@ -206,40 +218,78 @@ public class NumberBuilder { } @NotNull - private static String toString(@NotNull Double value, @NotNull NumeralBase nb) { - return CalculatorEngine.instance.getEngine().format(value, nb); + private static String formatNumber(@NotNull String number, @NotNull NumeralBase nb, boolean allowScientificFormat, @NotNull MathEngine engine) { + String result; + + if (allowScientificFormat) { + int indexOfDot = number.indexOf('.'); + + if (indexOfDot < 0) { + int indexOfE; + if (nb == NumeralBase.hex) { + indexOfE = -1; + } else { + indexOfE = number.indexOf(MathType.POWER_10); + } + if (indexOfE < 0) { + result = toString(number, nb, engine); + } else { + final String part; + if (indexOfDot != 0) { + part = toString(number.substring(0, indexOfE), nb, engine); + } else { + part = ""; + } + result = part + number.substring(indexOfE); + } + } else { + final String integerPart; + if (indexOfDot != 0) { + integerPart = toString(number.substring(0, indexOfDot), nb, engine); + } else { + integerPart = ""; + } + result = integerPart + number.substring(indexOfDot); + } + } else { + result = toString(number, nb, engine); + } + + return result; + } + + @NotNull + private static String toString(@NotNull String value, @NotNull NumeralBase nb, @NotNull MathContext mathContext) { + return mathContext.format(toDouble(value, nb, mathContext), nb); } public boolean isHexMode() { - return nb == NumeralBase.hex || ( nb == null && defaultNumeralBase == NumeralBase.hex); + return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex); } @NotNull - private NumeralBase getNumeralBase(){ - return nb == null ? defaultNumeralBase : nb; + private NumeralBase getNumeralBase() { + return nb == null ? engine.getNumeralBase() : nb; } - + @NotNull - private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb) throws NumberFormatException{ - - final MathEngine me = CalculatorEngine.instance.getEngine(); - - final NumeralBase defaultNb = me.getNumeralBase(); + private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb, @NotNull final MathContext mc) throws NumberFormatException { + final NumeralBase defaultNb = mc.getNumeralBase(); try { - me.setNumeralBase(nb); + mc.setNumeralBase(nb); try { - return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), me), null).content().doubleValue(); + return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue(); } catch (ParseException e) { try { - return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), me), null).content()).doubleValue(); + return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue(); } catch (ParseException e1) { throw new NumberFormatException(); } } } finally { - me.setNumeralBase(defaultNb); + mc.setNumeralBase(defaultNb); } } } diff --git a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java index e9b83db9..266eabff 100644 --- a/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java +++ b/src/main/java/org/solovyev/android/calculator/model/ToJsclTextProcessor.java @@ -6,7 +6,6 @@ package org.solovyev.android.calculator.model; -import jscl.JsclMathEngine; import org.jetbrains.annotations.NotNull; import org.solovyev.android.calculator.StartsWithFinder; import org.solovyev.android.calculator.jscl.JsclOperation; @@ -41,7 +40,7 @@ class ToJsclTextProcessor implements TextProcessor { final StringBuilder sb = new StringBuilder(s); - final NumberBuilder nb = new NumberBuilder(true, CalculatorEngine.instance.getEngine().getNumeralBase()); + final NumberBuilder nb = new NumberBuilder(false, CalculatorEngine.instance.getEngine()); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == ' ') continue; startsWithFinder.setI(i); diff --git a/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java b/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java index ce81a80e..4bf66fa5 100644 --- a/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java +++ b/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java @@ -26,7 +26,7 @@ public class TextHighlighterTest { @Test public void testProcess() throws Exception { - TextProcessor textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance); + TextProcessor textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance); final Random random = new Random(new Date().getTime()); for (int i = 0; i < 1000; i++) { @@ -48,7 +48,7 @@ public class TextHighlighterTest { Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); - textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance); + textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance); Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString()); Assert.assertEquals("1E3", textHighlighter.process("1E3").toString()); Assert.assertEquals("20x:", textHighlighter.process("20x:").toString()); @@ -60,7 +60,7 @@ public class TextHighlighterTest { Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString()); Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString()); Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString()); - textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance); + textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance); textHighlighter.process("cannot calculate 3^10^10 !!!\n" + " unable to enter 0. FIXED\n" + diff --git a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java index b5e37602..0c19af30 100644 --- a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java +++ b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java @@ -183,6 +183,18 @@ public class CalculatorEngineTest { Assert.assertEquals("100", cm.evaluate(JsclOperation.numeric, "0.1E3").getResult()); Assert.assertEquals("3.957", cm.evaluate(JsclOperation.numeric, "ln(8)lg(8)+ln(8)").getResult()); + Assert.assertEquals("0.933", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult()); + + try { + cm.getEngine().setNumeralBase(NumeralBase.hex); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "0x:E/0x:F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "0x:E/0x:F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.numeric, "E/F").getResult()); + Assert.assertEquals("E/F", cm.evaluate(JsclOperation.simplify, "E/F").getResult()); + } finally { + cm.getEngine().setNumeralBase(NumeralBase.dec); + } + Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((0))))))").getResult()); Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getResult());