What is the right precedence of the math expression

16,420

Solution 1

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.

Solution 2

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

Solution 3

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).

Solution 4

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.

Share:
16,420
bancer
Author by

bancer

Careers profile: http://careers.stackoverflow.com/bancer Author of SprintDict for Android: http://sprintdict.bancer.net/

Updated on June 05, 2022

Comments

  • bancer
    bancer almost 2 years

    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.