From 4428e6a39269e969aa189f40c197fa8802adc64d Mon Sep 17 00:00:00 2001 From: serso Date: Sat, 12 Nov 2011 18:49:26 +0400 Subject: [PATCH] support for entering E number --- res/layout/calc_plus_button.xml | 1 + .../android/calculator/math/MathType.java | 8 +-- .../calculator/model/NumberBuilder.java | 59 ++++++++++++++----- .../calculator/TextHighlighterTest.java | 12 +++- .../model/CalculatorEngineTest.java | 5 +- .../model/ToJsclTextProcessorTest.java | 31 +++++----- 6 files changed, 76 insertions(+), 40 deletions(-) diff --git a/res/layout/calc_plus_button.xml b/res/layout/calc_plus_button.xml index 17c9dbe6..92667e43 100644 --- a/res/layout/calc_plus_button.xml +++ b/res/layout/calc_plus_button.xml @@ -10,6 +10,7 @@ a:id="@+id/plusButton" calc:directionTextScale="0.5" calc:textUp="°" + calc:textDown="E" a:text="+" style="?digitButtonStyle" a:onClick="digitButtonClickHandler"/> \ No newline at end of file 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 8021c6a1..3a4cc2dd 100644 --- a/src/main/java/org/solovyev/android/calculator/math/MathType.java +++ b/src/main/java/org/solovyev/android/calculator/math/MathType.java @@ -43,12 +43,7 @@ public enum MathType { } }, - power_10(300, true, false, "E") { - @Override - protected String getSubstituteToJscl(@NotNull String match) { - return POWER_10_JSCL; - } - }, + power_10(300, false, false, "E"), postfix_function(400, false, true) { @NotNull @@ -260,7 +255,6 @@ public enum MathType { public static final List 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 = "√(-1)"; diff --git a/src/main/java/org/solovyev/android/calculator/model/NumberBuilder.java b/src/main/java/org/solovyev/android/calculator/model/NumberBuilder.java index 3a07a34c..765a2c45 100644 --- a/src/main/java/org/solovyev/android/calculator/model/NumberBuilder.java +++ b/src/main/java/org/solovyev/android/calculator/model/NumberBuilder.java @@ -13,11 +13,14 @@ import org.solovyev.common.utils.CollectionsUtils; import org.solovyev.common.utils.Finder; import org.solovyev.common.utils.MutableObject; +import java.util.ArrayList; +import java.util.List; + /** -* User: serso -* Date: 10/23/11 -* Time: 2:57 PM -*/ + * User: serso + * Date: 10/23/11 + * Time: 2:57 PM + */ public class NumberBuilder { @Nullable @@ -36,7 +39,8 @@ public class NumberBuilder { number = null; final MathType.Result possibleResult; - if (CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.dot, MathType.grouping_separator, MathType.power_10)) { + if (CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.dot, MathType.grouping_separator, MathType.power_10) || + isSignAfterE(mathTypeResult)) { if (numberBuilder == null) { numberBuilder = new StringBuilder(); } @@ -51,17 +55,31 @@ public class NumberBuilder { return possibleResult == null ? mathTypeResult : possibleResult; } + private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) { + if ("-".equals(mathTypeResult.getMatch()) || "+".equals(mathTypeResult.getMatch())) { + if (numberBuilder != null && numberBuilder.length() > 0) { + if (numberBuilder.charAt(numberBuilder.length() - 1) == MathType.POWER_10) { + return true; + } + } + } + return false; + } + @Nullable public MathType.Result process(@NotNull StringBuilder sb, @Nullable MutableObject numberOffset) { - int numberOfGroupingSeparators = 0; + int numberOfTokens = 0; if (numberBuilder != null) { try { number = numberBuilder.toString(); - for (String groupingSeparator : MathType.grouping_separator.getTokens()) { + List tokens = new ArrayList(); + tokens.addAll(MathType.grouping_separator.getTokens()); + tokens.add("+"); + for (String groupingSeparator : tokens) { String newNumber = number.replace(groupingSeparator, ""); - numberOfGroupingSeparators += number.length() - newNumber.length(); + numberOfTokens += number.length() - newNumber.length(); number = newNumber; } Double.valueOf(number); @@ -74,11 +92,11 @@ public class NumberBuilder { number = null; } - return replaceSystemVars(sb, number, numberOfGroupingSeparators, numberOffset); + return replaceSystemVars(sb, number, numberOfTokens, numberOffset); } @Nullable - private MathType.Result replaceSystemVars(StringBuilder sb, String number, int numberOfGroupingSeparators, @Nullable MutableObject numberOffset) { + private MathType.Result replaceSystemVars(StringBuilder sb, String number, int numberOfTokens, @Nullable MutableObject numberOffset) { MathType.Result result = null; if (number != null) { @@ -91,11 +109,11 @@ public class NumberBuilder { }); if (var != null) { - sb.delete(sb.length() - number.length() - numberOfGroupingSeparators, sb.length()); + sb.delete(sb.length() - number.length() - numberOfTokens, sb.length()); sb.append(var.getName()); result = new MathType.Result(MathType.constant, var.getName()); } else { - sb.delete(sb.length() - number.length() - numberOfGroupingSeparators, sb.length()); + sb.delete(sb.length() - number.length() - numberOfTokens, sb.length()); final String formattedNumber; @@ -103,9 +121,20 @@ public class NumberBuilder { int indexOfDot = number.indexOf('.'); if (indexOfDot < 0) { - formattedNumber = CalculatorEngine.instance.format(Double.valueOf(number), false); + int indexOfE = number.indexOf('E'); + if (indexOfE < 0) { + formattedNumber = CalculatorEngine.instance.format(Double.valueOf(number), false); + } else { + final String part; + if (indexOfDot != 0) { + part = CalculatorEngine.instance.format(Double.valueOf(number.substring(0, indexOfE)), false); + } else { + part = ""; + } + formattedNumber = part + number.substring(indexOfE); + } } else { - String integerPart = null; + final String integerPart; if (indexOfDot != 0) { integerPart = CalculatorEngine.instance.format(Double.valueOf(number.substring(0, indexOfDot)), false); } else { @@ -118,7 +147,7 @@ public class NumberBuilder { } if (numberOffset != null) { - numberOffset.setObject(formattedNumber.length() - number.length() - numberOfGroupingSeparators); + numberOffset.setObject(formattedNumber.length() - number.length() - numberOfTokens); } sb.append(formattedNumber); } diff --git a/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java b/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java index 3ad1639c..2a14a103 100644 --- a/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java +++ b/src/test/java/org/solovyev/android/calculator/TextHighlighterTest.java @@ -22,7 +22,7 @@ public class TextHighlighterTest { @Test public void testProcess() throws Exception { - final TextProcessor textHighlighter = new TextHighlighter(0, true); + TextProcessor textHighlighter = new TextHighlighter(0, true); final Random random = new Random(new Date().getTime()); for (int i = 0; i < 1000; i++) { @@ -42,6 +42,16 @@ public class TextHighlighterTest { Assert.assertEquals(")", textHighlighter.process(")").toString()); Assert.assertEquals(")()(", textHighlighter.process(")()(").toString()); Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); + Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString()); + + textHighlighter = new TextHighlighter(0, false); + Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString()); + Assert.assertEquals("1E3", textHighlighter.process("1E3").toString()); + Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString()); + 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); 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 3e57e915..f9c4a85d 100644 --- a/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java +++ b/src/test/java/org/solovyev/android/calculator/model/CalculatorEngineTest.java @@ -153,6 +153,7 @@ public class CalculatorEngineTest { Assert.assertEquals("11∞t", cm.evaluate(JsclOperation.numeric, "t11∞").getResult()); Assert.assertEquals("-t+t^3", cm.evaluate(JsclOperation.numeric, "t(t-1)(t+1)").getResult()); + 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()); @@ -214,8 +215,8 @@ public class CalculatorEngineTest { cm.setPrecision(2); Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); cm.setPrecision(10); - Assert.assertEquals("12'345'678.899999999", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); - Assert.assertEquals("123'456'788.99999999", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult()); + Assert.assertEquals("12'345'678.9", cm.evaluate(JsclOperation.numeric, "1.23456789E7").getResult()); + Assert.assertEquals("123'456'789", cm.evaluate(JsclOperation.numeric, "1.234567890E8").getResult()); Assert.assertEquals("1'234'567'890.1", cm.evaluate(JsclOperation.numeric, "1.2345678901E9").getResult()); } diff --git a/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java b/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java index e7db7941..bcd76949 100644 --- a/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java +++ b/src/test/java/org/solovyev/android/calculator/model/ToJsclTextProcessorTest.java @@ -25,7 +25,7 @@ public class ToJsclTextProcessorTest { @Test public void testSpecialCases() throws ParseException { final ToJsclTextProcessor preprocessor = new ToJsclTextProcessor(); - Assert.assertEquals( "3^10^10", preprocessor.process("3^10^10").toString()); + Assert.assertEquals( "3^E10", preprocessor.process("3^E10").toString()); } @Test @@ -37,12 +37,12 @@ public class ToJsclTextProcessorTest { 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)*ln(1)*(2*10^-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString()); + Assert.assertEquals( "(0)*(1E)", preprocessor.process("[0][1E]").toString()); + Assert.assertEquals( "(0)*(1E1)", preprocessor.process("[0][1E1]").toString()); + Assert.assertEquals( "(0)*(1E-1)", preprocessor.process("[0][1E-1]").toString()); + Assert.assertEquals( "(0)*(1.E-1)", preprocessor.process("[0][1.E-1]").toString()); + Assert.assertEquals( "(0)*(2*E-1)", preprocessor.process("[0][2*E-1]").toString()); + Assert.assertEquals( "(0)*ln(1)*(2*E-1)", preprocessor.process("[0]ln(1)[2*E-1]").toString()); Assert.assertEquals( "sin(4)*asin(0.5)*√(2)", preprocessor.process("sin(4)asin(0.5)√(2)").toString()); Assert.assertEquals( "sin(4)*cos(5)", preprocessor.process("sin(4)cos(5)").toString()); Assert.assertEquals( "π*sin(4)*π*cos(√(5))", preprocessor.process("πsin(4)πcos(√(5))").toString()); @@ -50,14 +50,15 @@ public class ToJsclTextProcessorTest { Assert.assertEquals( "π*sin(4)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4)+πcos(√(5+i))").toString()); Assert.assertEquals( "π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("πsin(4.01)+πcos(√(5+i))").toString()); Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))").toString()); - Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))*10^2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString()); - Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))*10^-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString()); - Assert.assertEquals( "10^2", preprocessor.process("E2").toString()); - Assert.assertEquals( "10^-2", preprocessor.process("E-2").toString()); - Assert.assertEquals( "10^-1/2", preprocessor.process("E-1/2").toString()); - Assert.assertEquals( "10^-1.2", preprocessor.process("E-1.2").toString()); - Assert.assertEquals( "10^(-1.2)", preprocessor.process("E(-1.2)").toString()); - Assert.assertEquals( "10^10^", preprocessor.process("EE").toString()); + Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E2").toString()); + Assert.assertEquals( "e^π*sin(4.01)+π*cos(√(5+(√(-1))))E-2", preprocessor.process("e^πsin(4.01)+πcos(√(5+i))E-2").toString()); + Assert.assertEquals( "E2", preprocessor.process("E2").toString()); + Assert.assertEquals( "E-2", preprocessor.process("E-2").toString()); + Assert.assertEquals( "E-1/2", preprocessor.process("E-1/2").toString()); + Assert.assertEquals( "E-1.2", preprocessor.process("E-1.2").toString()); + Assert.assertEquals( "E+1.2", preprocessor.process("E+1.2").toString()); + Assert.assertEquals( "E(-1.2)", preprocessor.process("E(-1.2)").toString()); + Assert.assertEquals( "EE", preprocessor.process("EE").toString()); try { preprocessor.process("ln()"); Assert.fail();