Solved

arithmetic expression

Posted on 2001-06-17
31
745 Views
Last Modified: 2007-12-19
Im making a arithmetic expression for java right now, it takes strings and caculates it... heres what ive been working on

First im scanning through the string to find all the statements that are surrounding the code

Then i find out how "deep" they are, for order of operations

then i plan on adding them to a array of string, and adding the depth(or order) on first

then sort the array depending on the depth

then calculating it

is this really the best way?/
0
Comment
Question by:amcteer
  • 14
  • 11
  • 2
  • +4
31 Comments
 

Author Comment

by:amcteer
ID: 6200272
oops heres some more info

an example string would be like
(23+12(6*2))

this is a method im writing in java

the only operators are
+ - / *

pretty simple i guess
0
 
LVL 4

Expert Comment

by:k.jones
ID: 6200349
Don't really know what you are about, but suspect that you would do better to use StringBuffer instead of String.

Traditional approach to handling nesting an arithmetic parsing would use stacks.  However, I do not know how that would fit with what you are doing.

Cheers,
Ken Jones
0
 
LVL 3

Expert Comment

by:sghosh092199
ID: 6200367
The String method seems to be OK. Since the operators are binary, you can consider creating an Op object as follows:

public class Op
{
  int depth;
  String operand;
  int op1;
  int op2;
  int result;


  public Op(int depth, String operand,  int op1,  int op2, int result)
{
..
}

}

As you scan the Expression, you can create Op objects and store them in an ArrayList. Depending on the depth, the results will be populated by subsequent iterations of the ArrayList.



0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:sghosh092199
ID: 6200372
k.jones: we were writing the comments simultaneously. So, the first statement is not in response to yours.
0
 
LVL 3

Expert Comment

by:superschlonz
ID: 6200474
If you want to evaluate simple expressions it might be the right way
to do it 'by hand' but if they get too complex you should better think
about some tool which do the work for you.

For example JLex and java_cup can generate the code for you.

JLex generates a lexical analyzer (also called scanner or lexer) which
scans for tokens in the input. These tokens can be single characters
or keywords or numbers or something else.

java_cup is a parser generator. The parser needs a scanner returning
tokens and then does the actions you defined with the tokens it gets.

With these two you can generate your own programming languages.

JLex: http://www.cs.princeton.edu/~appel/modern/java/JLex/
CUP: http://www.cs.princeton.edu/~appel/modern/java/CUP/
and a tutorial: http://www.hio.hen.nl/~vanleeuw/cano/tutorial.html
0
 
LVL 3

Expert Comment

by:Sendoh
ID: 6200688
hi !
guess what k.jones was the most suitable answer....
by using stack would be efficient for ur scenario...
if u interested i can post some code...:)
0
 

Author Comment

by:amcteer
ID: 6200705
Heres my parse meth, what i did was pad the string with a big A at the end.. kinda jury rigged my own EOF... now what im doing is calling my other meth findNExt, to scan and return the position for my concat...

look good so far?

public void nestCalc(String strCalc, int nestTotal)
{
  int startPos = 0;
  int lastPos = 0;
  //System.out.println(strCalc);
  //Search and rip(parse) the string
  for(startPos = 0; startPos < strCalc.length(); startPos++)
  {
    if ((strCalc.charAt(startPos) != '(') && strCalc.charAt(startPos) != ')' && strCalc.charAt(startPos) != 'A')
    {

      lastPos = findNext(startPos, strCalc);
      String buffer = strCalc.substring(startPos,lastPos);
      System.out.println(buffer);
      startPos = lastPos;
    }
    System.out.println(startPos);
  }

}
0
 

Author Comment

by:amcteer
ID: 6200707
whats eventually gunna happen is instead of printing out the result, im going to assign it to an array, then sort that, then output

i guess im making a "java math scripting engine" ??
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6201471
You can use
java.util.StringTokenizer parse = new java.util.StringTokenizer("1+8*(45+20)", "+-/*()", true);

while (parse.hasMoreTokens())
{
    String token = parse.nextToken();
    ....
}

instead your code

Andrey
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6201983
0
 
LVL 2

Accepted Solution

by:
Andrey_Kulik earned 210 total points
ID: 6201998
0
 

Author Comment

by:amcteer
ID: 6202002
hey, thats good i use the tokenizer to break it up... now i guess my problem is doing the order of operations, ive come up with so many different things.. but this stupid computer cant learn dammit!:)

any ideas?

i figred id determine the "depth" of the nesting, and then add it to a "que" depending on its depth, then just do all tha math..
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202005
I cannot send the source !!!! WHY ?


0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202008
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202014
give me your email please...
Andrey
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202033
Hi

this is source code for your problem (based on Stack)
Exists some technique of parsing this expressions... this is primary

FIRST PART


public class Calculator {

public Calculator() {
     super();
}

public static void main(String[] args)
{
     try
     {
          String s = "a+7*(t%10-2)^b";
          java.util.Hashtable h = new java.util.Hashtable();
          h.put("a", new Integer(10));
          h.put("b", new Integer(3));
          h.put("t", new Integer(14));
         
          System.out.println(Calculator.calculate(s, h));
     } catch (Exception e) {
          e.printStackTrace();
     }
}

static public int operation(char op, int value1, int value2) {
     switch (op)
     {
          case '+': return value1 + value2;
          case '-': return value1 - value2;
          case '*': return value1 * value2;
          case '/': return value1 / value2;
          case '%': return value1 % value2;
          case '^': return (int)Math.pow(value1,value2);
          case '(': return value1;
          case ')': return value1;
     }
     return 0;
}
}

Best regards
Andrey
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202036
SECOND PART

static public int calculate(String expression, java.util.Hashtable variables) throws IllegalArgumentException {
     // set operations priority
     java.util.Hashtable ops = new java.util.Hashtable();
     ops.put("+", new Integer(0));
     ops.put("-", new Integer(0));
     ops.put("*", new Integer(1));
     ops.put("/", new Integer(1));
     ops.put("%", new Integer(1));
     ops.put("^", new Integer(2));

     // set of operations
     String operations = "+-/*%^";
     
     java.util.StringTokenizer parse = new java.util.StringTokenizer(expression, operations + "()", true);

     // stack of operations
     java.util.Stack opStack = new java.util.Stack();
     // stack of variables
     java.util.Stack varStack = new java.util.Stack();

     // stacks for () sequences
     java.util.Stack bufOpStack = new java.util.Stack();
     java.util.Stack bufVarStack = new java.util.Stack();

     int value = 0;
     
     while (parse.hasMoreTokens())
     {
          String token = parse.nextToken();

          if (token.equals("("))
          {
               varStack.push(new Integer(value));
               // create new stacks for operations and variables
               bufOpStack.push(opStack);
               bufVarStack.push(varStack);
               opStack = new java.util.Stack();
               varStack = new java.util.Stack();
          } else
          if (token.equals(")"))
          {
               // do all operations in stack
               while (!opStack.isEmpty())
                    value = operation(((String)opStack.pop()).charAt(0), ((Integer)varStack.pop()).intValue(), value);
               
               opStack = (java.util.Stack)bufOpStack.pop();
               varStack = (java.util.Stack)bufVarStack.pop();
          } else
          if (operations.indexOf(token) >= 0)
          {
               // get priority for current operation
               Integer priority = (Integer)ops.get(token);

               // do all operations wich has higher priority
               while (!opStack.isEmpty() && priority.compareTo(ops.get(opStack.peek())) <= 0)
                    value = operation(((String)opStack.pop()).charAt(0), ((Integer)varStack.pop()).intValue(), value);

               // push operation in stack
               opStack.push(token);
          } else {
               varStack.push(new Integer(value));
               try
               {
                    // try to get integer value of token
                    value = Integer.parseInt(token);
               } catch (Exception e) {
                    // try to get integer value by name from variables
                    if (variables == null)
                         throw new IllegalArgumentException("Variables is null or bad variable : " + token);
                         
                    Integer variable = (Integer)variables.get(token);
                   
                    if (variable == null)
                         throw new IllegalArgumentException("Bad variable : " + token);
                         
                    value = ((Integer)variables.get(token)).intValue();
               }
          }
     }

     // do all operations in stack
     while (!opStack.isEmpty())
          value = operation(((String)opStack.pop()).charAt(0), ((Integer)varStack.pop()).intValue(), value);
     
     return value;
}
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6202048
Therea are TWO PART of Calculator class

make it together and try.

Hope this helps
Andrey
0
 
LVL 19

Expert Comment

by:Jim Cakalic
ID: 6202318
In response to a similar question, someone wanted to write a boolean algebra interpreter, I made the comments which I have reposted below. Unless you want to (research) or must (school assignment) write your own arithmetic expression evaluator, you might consider this option.

Programming languages have to pretty much all be able to evaluate boolean expressions. The specific syntax they use tends to vary. But Java has a full complement of boolean operators that can be applied. If only we could somehow dynamically interpret an expression with run-time applied variable values ...

BeanShell can! BeanShell is a small, free, embeddable, Java source interpreter with object scripting language features, written in Java. BeanShell executes standard Java statements and expressions, in addition to obvious scripting commands and syntax. In short: BeanShell is a dynamically interpreted Java. You can call BeanShell from your Java applications to execute Java code dynamically at run-time.

The downside of this is that you must use the Java operators instead of word operators. Here is how the Java code would look using the BeanShell Interpreter:

import bsh.Interpreter;
import bsh.EvalError;

public class BooleanEval {

   public static void main(String[] args) {
       boolean truth = false;
       try {
           Interpreter ntp = new Interpreter();
           ntp.setVariable("a", true);
           ntp.setVariable("b", false);
           ntp.setVariable("c", true);
           ntp.setVariable("d", true);
           ntp.setVariable("e", true);
           ntp.eval("truth = a && b && ( c || !(d || e) ) == a && b && c && d;");
           truth = ((Boolean)ntp.getVariable("truth")).booleanValue();
       } catch (EvalError e) {
           e.printStackTrace();
       }
       System.out.println(truth);
   }
}

This is fairly simple and straightforward. I tell the Interpreter about my variables and their values. I ask it to interpret a statement using those variables and assign the value to a new variable called "truth". Then I ask for the value of "truth" which is returned as a Boolean object.

Best regards,
Jim Cakalic
0
 

Author Comment

by:amcteer
ID: 6205114
Andrey_Kulik, im sorry but the calculator uses doubles.. im getting pretty close with mine but i cant get it to work with some of the following sample data

 -1.2 * 112.7  =  -135.24
 17.2 + 3.6 * 2  =  24.4
 (11.8 + 13.2)/(2 * 4 + 2) =  2.5
 -(((8.5 + 0.5)* 2)+ 12.7) =  30.7
 139.6 * + 1.2  =  167.52
 84.6 - - 13.2  =  97.8
 93.3 * /3  =  Exception: expIllegalArithmeticExpression
 12.2A - 3.4  =  Exception: expIllegalArithmeticExpression
 (((16 + 25) * 7) =  Exception: expUnmatchedParentheses

ive got about %60 of it going, but i think im doing it very sloopy... could someone help me with this?
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6205337
You should do some changes in source

IT'S VERY SIMPLY


FIRST PART

static public double operation(char op, double value1, double value2) {
     switch (op)
     {
          case '+': return value1 + value2;
          case '-': return value1 - value2;
          case '*': return value1 * value2;
          case '/': return value1 / value2;
          case '%': return value1 % value2;
          case '^': return Math.pow(value1,value2);
     }
     return 0;
}

public static void main(String[] args)
{
     try
     {
          String s = "a+7*(t%10-2)^b";
          java.util.Hashtable h = new java.util.Hashtable();
          h.put("a", new Double(10.2));
          h.put("b", new Double(3.1));
          h.put("t", new Double(14.3));
         
          System.out.println(Calculator.calculate(s, h));
     } catch (Exception e) {
          e.printStackTrace();
     }
}

0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6205339
SECOND PART

static public double calculate(String expression, java.util.Hashtable variables) throws IllegalArgumentException {
     // set operations priority
     java.util.Hashtable ops = new java.util.Hashtable();
     ops.put("+", new Integer(0));
     ops.put("-", new Integer(0));
     ops.put("*", new Integer(1));
     ops.put("/", new Integer(1));
     ops.put("%", new Integer(1));
     ops.put("^", new Integer(2));

     // set of operations
     String operations = "+-/*%^";
     
     java.util.StringTokenizer parse = new java.util.StringTokenizer(expression, operations + "()", true);

     // stack of operations
     java.util.Stack opStack = new java.util.Stack();
     // stack of variables
     java.util.Stack varStack = new java.util.Stack();

     // stacks for () sequences
     java.util.Stack bufOpStack = new java.util.Stack();
     java.util.Stack bufVarStack = new java.util.Stack();

     double value = 0;
     
     while (parse.hasMoreTokens())
     {
          String token = parse.nextToken();

          if (token.equals("("))
          {
               varStack.push(new Double(value));
               // create new stacks for operations and variables
               bufOpStack.push(opStack);
               bufVarStack.push(varStack);
               opStack = new java.util.Stack();
               varStack = new java.util.Stack();
          } else
          if (token.equals(")"))
          {
               // do all operations in stack
               while (!opStack.isEmpty())
                    value = operation(((String)opStack.pop()).charAt(0), ((Double)varStack.pop()).doubleValue(), value);
               
               opStack = (java.util.Stack)bufOpStack.pop();
               varStack = (java.util.Stack)bufVarStack.pop();
          } else
          if (operations.indexOf(token) >= 0)
          {
               // get priority for current operation
               Integer priority = (Integer)ops.get(token);

               // do all operations wich has higher priority
               while (!opStack.isEmpty() && priority.compareTo(ops.get(opStack.peek())) <= 0)
                    value = operation(((String)opStack.pop()).charAt(0), ((Double)varStack.pop()).doubleValue(), value);

               // push operation in stack
               opStack.push(token);
          } else {
               varStack.push(new Double(value));
               try
               {
                    // try to get integer value of token
                    value = Double.parseDouble(token);
               } catch (Exception e) {
                    // try to get integer value by name from variables
                    if (variables == null)
                         throw new IllegalArgumentException("Variables is null or bad variable : " + token);
                         
                    Double variable = (Double)variables.get(token);
                   
                    if (variable == null)
                         throw new IllegalArgumentException("Bad variable : " + token);
                         
                    value = ((Double)variables.get(token)).doubleValue();
               }
          }
     }

     // do all operations in stack
     while (!opStack.isEmpty())
          value = operation(((String)opStack.pop()).charAt(0), ((Double)varStack.pop()).doubleValue(), value);
     
     return value;
}
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6205356
This source work with CORRECT expression on input

If you wanna catch other exception you should do the following

try
{
  while (!opStack.isEmpty())
    value = operation(((String)opStack.pop()).charAt(0), ((Double)varStack.pop()).doubleValue(), value);

} catch (Exception e) { // expIllegalArithmeticExpression
  throw new IllegalArgumentException("expIllegalArithmeticExpression");
}

AND

try
{
  while (!opStack.isEmpty() && priority.compareTo(ops.get(opStack.peek())) <= 0)
    value = operation(((String)opStack.pop()).charAt(0), ((Double)varStack.pop()).doubleValue(), value);

} catch (Exception e) { // expIllegalArithmeticExpression
  throw new IllegalArgumentException("expIllegalArithmeticExpression");
}

INSTEAD correspondingly source code parts

AND

try
{
  opStack = (java.util.Stack)bufOpStack.pop();
  varStack = (java.util.Stack)bufVarStack.pop();
} catch (Exception e) {
  throw new IllegalArgumentException("expUnmatchedParentheses");
}



Andrey

0
 

Author Comment

by:amcteer
ID: 6205995
Ok, that looks really good.. one thing im trying to figure out is this

String s = "a+7*(t%10-2)^b";
         java.util.Hashtable h = new java.util.Hashtable();
         h.put("a", new Double(10.2));
         h.put("b", new Double(3.1));
         h.put("t", new Double(14.3));

Could you explain to me breifly what a hash table is? and how would i make this accept the other values?
ie for
-(((8.5 + 0.5)* 2)+ 12.7) =  30.7 would i put
"-a(((t%8.5 + 0.5)^b*2)^b+12.7)"
???

im sorry for asking so many questions, you've been a great help to me, ill up the points (with what i can do)
0
 

Author Comment

by:amcteer
ID: 6206063
instead of just saying
String s = "a+7*(t%10-2)^b";
i want to pass in strings and append those a-t and b "hash codes?"
ive been tinkering around with that but ive been having a few problems..
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6206263
You can define some literal constant
f.e.

String s = "abc+10*te";
java.util.Hashtable h = new java.util.Hashtable();
h.put("abc", new Double(125));
h.put("te", new Double(78.4));

Calculator.calculate(s, h);
  and the same
Calculator.calculate("125+10*78.4", null);

This contants will be replace on real values (during parsing expression)

Andrey




0
 
LVL 2

Expert Comment

by:Andrey_Kulik
ID: 6206284
Hi
I find an error:

after
  varStack.push(new Double(value));
you must add the following line
  value = 0; // NEW LINE

this error was in "7+5(-10)" expression

Andrey
0
 

Author Comment

by:amcteer
ID: 6207503
ok i really dont understand what the use of your hashtable is for, can you make a version of calculator that all i do is pass it string values?  thats what im trying to do, im not to familiar with this hashtable and its really slowing me down
0
 

Author Comment

by:amcteer
ID: 6208731
im going to accept your work, but if you could just send me an email with a working example? possibly if i just could call the method by giving it a string ie "2*4 /2" and it returning a double?
0
 

Author Comment

by:amcteer
ID: 6208734
my email being amcteer@sympatico.ca
0
 

Author Comment

by:amcteer
ID: 6208980
OK NEVERMIND
i figured it out, wow.. it took a while but i had to read a few things and such...

THANK YOU SO MUCH
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
even odd program using while loop 3 72
Is there a simpler dropbox system? 10 44
java mysql insert application 14 41
Where to place postgres JDBC driver jar on tomcat 8 24
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…

680 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question