arithmetic expression

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?/
Who is Participating?

Commented:
0

Author Commented:

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

Commented:
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

Commented:
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

Commented:
k.jones: we were writing the comments simultaneously. So, the first statement is not in response to yours.
0

Commented:
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

Commented:
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 Commented:
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 Commented:
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

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

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

Andrey
0

Commented:
0

Author Commented:
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

Commented:
I cannot send the source !!!! WHY ?

0

Commented:
0

Commented:
Andrey
0

Commented:
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

Commented:
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

Commented:
Therea are TWO PART of Calculator class

make it together and try.

Hope this helps
Andrey
0

Senior Developer/ArchitectCommented:
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 Commented:
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

Commented:
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

Commented:
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

Commented:
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");
}

AND

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

Andrey

0

Author Commented:
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 Commented:
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

Commented:
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

Commented:
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 Commented:
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 Commented:
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 Commented:
my email being amcteer@sympatico.ca
0

Author Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.