summaryrefslogtreecommitdiffstats
path: root/src/com/android/calculator2/CalculatorExpr.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/calculator2/CalculatorExpr.java')
-rw-r--r--src/com/android/calculator2/CalculatorExpr.java85
1 files changed, 63 insertions, 22 deletions
diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java
index 2162bb2..3023b5c 100644
--- a/src/com/android/calculator2/CalculatorExpr.java
+++ b/src/com/android/calculator2/CalculatorExpr.java
@@ -79,19 +79,22 @@ class CalculatorExpr {
// Supports addition and removal of trailing characters; hence mutable.
private static class Constant extends Token implements Cloneable {
private boolean mSawDecimal;
- String mWhole; // part before decimal point
- private String mFraction; // part after decimal point
+ String mWhole; // String preceding decimal point.
+ private String mFraction; // String after decimal point.
+ private int mExponent; // Explicit exponent, only generated through addExponent.
Constant() {
mWhole = "";
mFraction = "";
- mSawDecimal = false;
+ mSawDecimal = false;
+ mExponent = 0;
};
Constant(DataInput in) throws IOException {
mWhole = in.readUTF();
mSawDecimal = in.readBoolean();
mFraction = in.readUTF();
+ mExponent = in.readInt();
}
@Override
@@ -100,19 +103,33 @@ class CalculatorExpr {
out.writeUTF(mWhole);
out.writeBoolean(mSawDecimal);
out.writeUTF(mFraction);
+ out.writeInt(mExponent);
}
// Given a button press, append corresponding digit.
// We assume id is a digit or decimal point.
// Just return false if this was the second (or later) decimal point
// in this constant.
+ // Assumes that this constant does not have an exponent.
boolean add(int id) {
if (id == R.id.dec_point) {
- if (mSawDecimal) return false;
+ if (mSawDecimal || mExponent != 0) return false;
mSawDecimal = true;
return true;
}
int val = KeyMaps.digVal(id);
+ if (mExponent != 0) {
+ if (Math.abs(mExponent) <= 10000) {
+ if (mExponent > 0) {
+ mExponent = 10 * mExponent + val;
+ } else {
+ mExponent = 10 * mExponent - val;
+ }
+ return true;
+ } else { // Too large; refuse
+ return false;
+ }
+ }
if (mSawDecimal) {
mFraction += val;
} else {
@@ -121,10 +138,18 @@ class CalculatorExpr {
return true;
}
+ void addExponent(int exp) {
+ // Note that adding a 0 exponent is a no-op. That's OK.
+ mExponent = exp;
+ }
+
// Undo the last add.
// Assumes the constant is nonempty.
void delete() {
- if (!mFraction.isEmpty()) {
+ if (mExponent != 0) {
+ mExponent /= 10;
+ // Once zero, it can only be added back with addExponent.
+ } else if (!mFraction.isEmpty()) {
mFraction = mFraction.substring(0, mFraction.length() - 1);
} else if (mSawDecimal) {
mSawDecimal = false;
@@ -146,28 +171,24 @@ class CalculatorExpr {
result += '.';
result += mFraction;
}
- return KeyMaps.translateResult(result);
- }
-
- // Eliminates leading decimal, which some of our
- // other packages don't like.
- // Meant for machine consumption:
- // Doesn't internationalize decimal point or digits.
- public String toEasyString() {
- String result = mWhole;
- if (result.isEmpty()) result = "0";
- if (mSawDecimal) {
- result += '.';
- result += mFraction;
+ if (mExponent != 0) {
+ result += "E" + mExponent;
}
- return result;
+ return KeyMaps.translateResult(result);
}
+ // Return non-null BoundedRational representation.
public BoundedRational toRational() {
String whole = mWhole;
if (whole.isEmpty()) whole = "0";
BigInteger num = new BigInteger(whole + mFraction);
BigInteger den = BigInteger.TEN.pow(mFraction.length());
+ if (mExponent > 0) {
+ num = num.multiply(BigInteger.TEN.pow(mExponent));
+ }
+ if (mExponent < 0) {
+ den = den.multiply(BigInteger.TEN.pow(-mExponent));
+ }
return new BoundedRational(num, den);
}
@@ -186,6 +207,7 @@ class CalculatorExpr {
res.mWhole = mWhole;
res.mFraction = mFraction;
res.mSawDecimal = mSawDecimal;
+ res.mExponent = mExponent;
return res;
}
}
@@ -350,6 +372,15 @@ class CalculatorExpr {
}
}
+ boolean hasTrailingConstant() {
+ int s = mExpr.size();
+ if (s == 0) {
+ return false;
+ }
+ Token t = mExpr.get(s-1);
+ return t instanceof Constant;
+ }
+
private boolean hasTrailingBinary() {
int s = mExpr.size();
if (s == 0) return false;
@@ -410,6 +441,15 @@ class CalculatorExpr {
}
/**
+ * Add exponent to the constant at the end of the expression.
+ * Assumes there is a constant at the end of the expression.
+ */
+ void addExponent(int exp) {
+ Token lastTok = mExpr.get(mExpr.size() - 1);
+ ((Constant) lastTok).addExponent(exp);
+ }
+
+ /**
* Remove trailing op_add and op_sub operators.
*/
void removeTrailingAdditiveOperators() {
@@ -595,18 +635,19 @@ class CalculatorExpr {
// that was not used as part of the evaluation.
private EvalRet evalUnary(int i, EvalContext ec) throws SyntaxException {
Token t = mExpr.get(i);
+ BoundedRational ratVal;
CR value;
if (t instanceof Constant) {
Constant c = (Constant)t;
- value = CR.valueOf(c.toEasyString(),10);
- return new EvalRet(i+1, value, c.toRational());
+ ratVal = c.toRational();
+ value = ratVal.CRValue();
+ return new EvalRet(i+1, value, ratVal);
}
if (t instanceof PreEval) {
PreEval p = (PreEval)t;
return new EvalRet(i+1, p.mValue, p.mRatValue);
}
EvalRet argVal;
- BoundedRational ratVal;
switch(((Operator)(t)).mId) {
case R.id.const_pi:
return new EvalRet(i+1, CR.PI, null);