All Downloads are FREE. Search and download functionalities are using the official Maven repository.

util.Expression Maven / Gradle / Ivy

There is a newer version: 20240707
Show newest version
// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package util;

public class Expression {
  /*
   * Strings used for storing expression.
   */
  private String s, x;
  private boolean isInvalid;

  /*
   * Term evaluator for number literals.
   */
  private double term() {
    double ans = 0;
    StringBuffer temp = new StringBuffer();
    while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
      temp.append(Integer.parseInt("" + s.charAt(0)));
      advance();
    }
    if (s.length() > 0 && s.charAt(0) == '.') {
      temp.append('.');
      advance();
      while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
        temp.append(Integer.parseInt("" + s.charAt(0)));
        advance();
      }
    }
    if (s.length() > 0 && (s.charAt(0) == 'e' || s.charAt(0) == 'E')) {
      temp.append('e');
      advance();
      temp.append(s.charAt(0));
      advance();
      while (s.length() > 0 && Character.isDigit(s.charAt(0))) {
        temp.append(Integer.parseInt("" + s.charAt(0)));
        advance();
      }
    }

    if (temp.length() == 0) //...invalid expression term
      isInvalid = true;
    else
      ans = Double.valueOf(temp.toString());

    return ans;
  }

  /*
   * Parentheses solver.
   */
  private double paren() {
    double ans;
    if (s.charAt(0) == '(') {
      advance();
      ans = add();
      advance();
    } else {
      ans = term();
    }
    return ans;
  }

  /*
   * Exponentiation solver.
   */
  private double exp() {
    boolean neg = false;
    if (s.charAt(0) == '-') {
      neg = true;
      advance();
    }
    double result = paren();
    while (s.length() > 0) {
      if (s.charAt(0) == '^') {
        result = exponentiate(result);
      } else
        break;
    }
    if (neg)
      result *= -1;
    return result;
  }

  private double exponentiate(double result) {
    advance();
    boolean expNeg = false;
    if (s.charAt(0) == '-') {
      expNeg = true;
      advance();
    }
    double e = paren();
    if (result < 0)
      result = exponentiateNegativeNumber(result, expNeg, e);
    else if (expNeg)
      result = Math.exp(-e * Math.log(result));
    else
      result = Math.exp(e * Math.log(result));
    return result;
  }

  private void advance() {
    s = s.substring(1);
  }

  private double exponentiateNegativeNumber(double result, boolean expNeg, double e) {
    if (Math.ceil(e) == e) {
      result = calculateIntegralExponent(result, expNeg, e);
    } else {
      result = Double.NaN;
    }
    return result;
  }

  private double calculateIntegralExponent(double result, boolean expNeg, double e) {
    double x = 1;
    if (expNeg)
      e *= -1;
    if (e == 0)
      result = 1;
    else if (e > 0)
      for (int i = 0; i < e; i++)
        x *= result;
    else
      for (int i = 0; i < -e; i++)
        x /= result;
    result = x;
    return result;
  }

  /*
   * Trigonometric function solver.
   */
  private double trig() {
    double ans = 0;
    boolean found = false;
    if (s.indexOf("sin") == 0) {
      s = s.substring(3);
      ans = Math.sin(trig());
      found = true;
    } else if (s.indexOf("cos") == 0) {
      s = s.substring(3);
      ans = Math.cos(trig());
      found = true;
    } else if (s.indexOf("tan") == 0) {
      s = s.substring(3);
      ans = Math.tan(trig());
      found = true;
    }
    if (!found) {
      ans = exp();
    }
    return ans;
  }

  /*
   * Multiplication, division expression solver.
   */
  private double mul() {
    double ans = trig();
    if (s.length() > 0) {
      while (s.length() > 0) {
        if (s.charAt(0) == '*') {
          advance();
          ans *= trig();
        } else if (s.charAt(0) == '/') {
          advance();
          ans /= trig();
        } else break;
      }
    }
    return ans;
  }

  /*
   * Addition, subtraction expression solver.
   */
  private double add() {
    double ans = mul();
    while (s.length() > 0) {
      if (s.charAt(0) == '+') {
        advance();
        ans += mul();
      } else if (s.charAt(0) == '-') {
        advance();
        ans -= mul();
      } else {
        break;
      }
    }
    return ans;
  }

  /*
   * Public access method to evaluate this expression.
   */
  public Maybe evaluate() {
    isInvalid = false;
    s = x.intern();
    double last = add();
    return isInvalid ? Maybe.noDouble : new Maybe(last);
  }

  /*
   * Creates new Expression.
   */
  public Expression(String s) {
    // remove white space, assume only spaces or tabs
    x = s.replaceAll("[ \t]", "");
  }

  /*
   * The String value of this Expression.
   */
  public String toString() {
    return x.intern();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy