views:

214

answers:

8

What is the correct sequence of the math operations in this expression in Java:

    a + b  * c / ( d - e )
1.    4    1   3     2
2.    4    2   3     1

I understand that result is the same in both answers. But I would like to fully understand the java compiler logic. What is executed first in this example - multiplication or the expression in parentheses? A link to the documentation that covers that would be helpful.

UPDATE: Thank you guys for the answers. Most of you write that the expression in parentheses is evaluated first. After looking at the references provided by Grodriguez I created little tests:

int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'

Could anybody explain why these tests produce different results? If the expression in parentheses is evaluated the first I would expect the same result - 9.

+10  A: 

As JeremyP has nicely shown us, the first answer is correct.

In general, the following rules apply:

  • Every operand of an operator is evaluated before the operation itself is performed (except for ||, &&, and ? :)
  • Operands are evaluated left to right. The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.
  • The order of evaluation respects parentheses and operator precedence:
    • Parentheses are evaluated first.
    • Operators are evaluated in order of precedence.
    • Operators with equal precedence are evaluated left-to-right, except for assignment operators which are evaluated right-to-left.

Note that the first two rules explain the result in your second question:

int i = 2;
System.out.println(i * (i=3)); // prints '6'
int j = 2;
System.out.println((j=3) * j); // prints '9'

Reference documentation:

http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#4779

Tutorial:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/operators.html

Grodriguez
+1 for the first link
bancer
This description is correct in terms of the result generated for the expression, but it is not always true to say "parentheses are evaluated first". If any of the things in parentheses are methods then this might be significant.
DJClayworth
The second answer is not correct. `*` and `/` have equal precendence and are left associative. The expression is therefore equivalent to ` a + ((b * c) / ( d - e ))`. Together with the rule that left operands are evaluated first, means that `b * c` is evaluated first.
JeremyP
"The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated" (from the first link). I assume this means that if the parentheses are on the right-hand side of an operand then they will be evaluated after whatever is on the left is evaluated. This would certainly explain Bancer's observations in his update. It doesn't seem worth adding a new answer to say that though so I thought I'd comment so you can update yours.
Chris
@Grodriguez: no. the multiplication will be evaluated before the subtraction because the left operand of the division is evaluated before the right operand of the division
JeremyP
@Grodriguez: please look at the test program I added to my answer below. It shows that the left side of the division is evaluated before the right side.
JeremyP
@JeremyP, Chris: You are right. Updating my answer.
Grodriguez
Answer edited and updated. Downvoters might want to reconsider.
Grodriguez
@Grodriguez: Reversed my vote and up voted because you were the first person to link to the JLS.
JeremyP
A: 

i am assuming that your expression would be something like

x = a + b * c / ( d - e )

the equality operator has right to left order of evaluation. so the expression on the right of = will be evaluated first.

if your refer this precedence chart: http://www.java-tips.org/java-se-tips/java.lang/what-is-java-operator-precedence.html

1) the brackets will be evaluated (d-e), lets say (d - e) = f so the expression then becomes x = a + b * c / f.

2) Now * and / have same precedence, but the order of evaluation is left to right to * will be evaluated first so lets say b * c = g, so the expression becomes x = a + g /f

3) Now / has the next precedence so g / f will be evaluated to lets say h so the expression will be come x = a + h,

4) lastly evaluating a + h

Amrish
*the equality operator*? You mean *the assignment operator*.
Alin Purcaru
A: 

The results of the calculation are defined by the Operator Order of Precedence. So parentheses have highest precedence here, multiplication and division next highest, and addition and subtraction lowest. Operators with equal precedence are evaluated left to right. So the expression in the question is equivalent to:

    a + (b  * c) / ( d - e ))

However there is a slight difference between what is normally meant by "being evaluated first" and the operator precedence for getting the correct answer.

"d-e" is not necessarily actually calculated before "a" is calculated. This pretty much doesn't make any difference unless one of the 'variables' in the expression is actually a function. The Java standard does not specify the order of evaluation of components of an expression.

DJClayworth
The text of your link appears to be contradicted by text it links to. It only includes a style guideline indicating too much reliance can cause confusing code.
ILMTitan
A: 
a + b * c / ( d - e )
      1         1
          2
  3

The whole point of operator precedence is to convert the expression into a syntax tree. Here the * and - are at the same level of the tree. Which one is evaluated first is irrelevant for the result and not warrantied.

Edit: Sorry, I got confused by my C background. As others have pointed out, Java has an "Evaluate Left-Hand Operand First" rule. Applying this rule to / tells you that * is evaluated first (your first answer).

Edgar Bonet
Are * and / not the same level of precedence? Is there any reason to believe that it will do the multiplication before the division or just because left to right puts the * before the /
Chris
Java enforces left-to-right for operators with the same precedence.
Grodriguez
From the [Java Specification](http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#239829): "[*, / and %] have the same precedence and are syntactically left-associative (they group left-to-right)."
Edgar Bonet
+7  A: 

Almost everybody so far has confused order of evaluation with operator precedence. In Java the precedence rules make the expression equivalent to the following:

a + (b  * c) / ( d - e )

because * and / have equal precedence and are left associative.

The order of evaluation is strictly defined as left hand operand first, then right, then operation (except for || and &&). So the order of evaluation is:

  a
      b
      c
    *
      d
      e
    -
  /
+

order of evaluation goes down the page. Indentation reflects the structure of the syntax tree

Edit

In response to Grodriguez's comments. The following program:

public class Precedence 
{
    private static int a()
    {
        System.out.println("a");
        return 1;
    }   
    private static int b()
    {
        System.out.println("b");
        return 2;
    }
    private static int c()
    {
        System.out.println("c");
        return 3;
    }
    private static int d()
    {
        System.out.println("d");
        return 4;
    }
    private static int e()
    {
        System.out.println("e");
        return 5;
    }

    public static void main(String[] args) 
    {
        int x = a() + b() * c() / (d() - e());
        System.out.println(x);
    } 
}

Produces the output

a
b
c
d
e
-5

which clearly shows the multiplication is performed before the subtraction.

JeremyP
"Java programming language implementations must respect the order of evaluation as indicated explicitly by parentheses and implicitly by operator precedence." (JLS, 15.7.3)
Grodriguez
@Grodriguez: "The left-hand operand of a binary operator appears to be fully evaluated before *any part* of the right-hand operand is evaluated." (JLS 15.7.1). [my emphasis]. The order of evaluation in my example fully complies with 15.7.3.
JeremyP
@JeremyP Wow, I wrote that exact same program to prove to myself I had it right.
ILMTitan
@JeremyP: You are right. +1.
Grodriguez
Out of interest do you have any reason to believe that the right operand of the multiply is just c as opposed to (c-(d-e))? I agree with your reasoning in general (and just played around testing such things in C# as demonstrated in my answer elsewhere) but I made the assumption that it would in essence be greedy with its matching for the right hand operator... I'm tryign to think of a way to test this currently...
Chris
@Chris Yes, the case where a=0, b=20, c=1, d=20 and e=0 comes out to 1 rather than 0.
ILMTitan
@Chris: Yes, operator precedence and left associativity. `*` and `/` have the same precedence. `-` would normally have lower precedence, but the parentheses give it the highest precedence. Left associativity gives the left hand of two equal precedence operators the highest precedence. So, in this case the * and - operators must both be evaluated before the /. The argument I was having with Grodriguez was about whether * should be evaluated before the -.
JeremyP
@Chris: And our argument would have been totally irrelevant (and the original question!) if no operand could have side effects when evaluated. The program I posted deliberately introduced a side effect (printing to System.out) to show the real evaluation order.
JeremyP
Thanks for the clarifications. Its been an interesting and fun ride to get to the answer. And maybe distracted me from work more than I intended. :)
Chris
@JeremyP: I wrote almost identical program as in your edit part but didn't believe the result thinking that maybe it was false because of method calls :)
bancer
+3  A: 

It evaluates the expressions in the following order. Variable names are expressions that need to be evaluated.

a + b * c / (d - e)
    2   3    5   6
      4        7
1         8
  9

So, the answer to your question is #1. The order of operations determines the shape of the expression tree (what is the left side of the tree, and what is the right), but the left side is always evaluated first (and the root is evaluated last).

ILMTitan
+1 for checking the answer against reality :)
JeremyP
A: 

In your second question, it seems Java is evaluating the part in parenthesis as an assignment, not an mathematical expression. This means that is will not perform parenthetical assignments in the same order as operations in parenthesis.

agross
Assignments **are** expressions!
Edgar Bonet
+1  A: 

I would imagine that it might evaluate something like this evaluating from left to right.

a+b*c/(d-e)

Action           Left Value      Right Value
Start Add        a               b*c/(d-e)
Start Multiply   b               c
Calc Multiply (since it can)    
Start Divide     b*c             (d-e)
Start Subtract   d               e
Calc Subtract
Calc Divide
Calc Add

This can be thought of as creating a binary tree representing the calculations and then working from the leaf nodes, left to right, calculating things. Unfortunately my ascii art isn't great but here's an attempt at representing the tree in question:

   Add
    /\
   /  \
  a    \
     Divide
       / \
      /   \
     /     \
    /       \
Multiply  Subtract
  /\         /\
 /  \       /  \
b    c     d    e

And I did some tests in C# (I know its not the same but that's where my interests lie and the tests can be easily adapted) as follows:

        f = 1;
        Console.WriteLine((f=2) + (f) * (f) / ((f) - (f)-1));
        Console.WriteLine(2 + 2 * 2 / (2 - 2 - 1));
        f = 1;
        Console.WriteLine((f) + (f=2) * (f) / ((f) - (f)-1));
        Console.WriteLine(1 + 2 * 2 / (2 - 2 - 1));
        f = 1;
        Console.WriteLine((f) + (f) * (f = 2) / ((f) - (f)-1));
        Console.WriteLine(1 + 1 * 2 / (2 - 2 - 1));
        f = 1;
        Console.WriteLine((f) + (f) * (f) / ((f=2) - (f)-1));
        Console.WriteLine(1 + 1 * 1 / (2 - 2 - 1));
        f = 1;
        Console.WriteLine((f) + (f) * (f) / ((f) - (f=2)-1));
        Console.WriteLine(1d + 1d * 1d / (1d - 2d - 1d));

The pairs of console.writeline statements are the algebraic one (using the set a number trick) and a numerical representation showing what the calculation actually does. The pairs produce the same result as each other.

As can be seen the arguments are evaluated in order with any after the assignment being 2 and those before being one. So the order of evaluation of things is simple left to right I think but the order of calculations is as you would expect it to be.

I assume this can be run almost with copy and paste to test in JAVA...

There may be some unnoticed assumptions in here so if anybody does spot logic flaws in here please do call me on them and I'll work them through.

Chris
Your tree is wrong. Multiply should be left side under Divide. Try the case where b=20, c=1, d=20 and e=0.
ILMTitan
No, Chris, it's `a+(b*c)/(d-e)`, not `a+b*(c/(d-e))`. Because *, / and % have left-associativity.
Edgar Bonet
ILMTitan: Presumably those numbers and using integers so that the c/(d-e) would be truncated to zero showing teh difference. I've not tried it in code but I see how it would work. :) Edgar Bonet: OK, yup. I see what you mean. Hadn't really spec checked enough it seems. Stands to reason that there is a rule. :) I'll update my awesome ascii art... ;-)
Chris