Solved

arithmetic expression

Posted on 2001-06-17
31
740 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 3

Expert Comment

by:sghosh092199
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
0
 
LVL 2

Accepted Solution

by:
Andrey_Kulik earned 210 total points
Comment Utility
0
 

Author Comment

by:amcteer
Comment Utility
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
Comment Utility
I cannot send the source !!!! WHY ?


0
 
LVL 2

Expert Comment

by:Andrey_Kulik
Comment Utility
0
 
LVL 2

Expert Comment

by:Andrey_Kulik
Comment Utility
give me your email please...
Andrey
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 2

Expert Comment

by:Andrey_Kulik
Comment Utility
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
Comment Utility
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
Comment Utility
Therea are TWO PART of Calculator class

make it together and try.

Hope this helps
Andrey
0
 
LVL 19

Expert Comment

by:Jim Cakalic
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
my email being amcteer@sympatico.ca
0
 

Author Comment

by:amcteer
Comment Utility
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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
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…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

771 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now