========================== Operators and precedence ========================== .. contents:: General concepts ================ Precedence ---------- It is customary in mathematics to omit parentheses to simplify complex expressions that use binary operators. For example we often write “:math:`3+2+1`” instead of the more complex “:math:`(3+2)+1`”. However as soon as we use different types of operators, the question immediately arises: is “:math:`1 + 2\times 3`” equal to “:math:`(1+2)\times 3`” or “:math:`1+(2\times 3)`”? In mathematics at least, we use *precedence rules* to disambiguate: we say that “multiplication has a *higher precedence* than addition”, so the sign :math:`\times` binds to its operands “tighter” than the sign :math:`+`. Since we have multiple operators in arithmetic at least, we use a *precedence table* to determine which operators bind tighter than others: ======================== =================================== Arithmetic operator Precedence (higher binds tighter) ======================== =================================== :math:`\times \div` 4 :math:`+ -` 3 :math:`= < > \leq \geq` 2 :math:`\Leftrightarrow` 1 ======================== =================================== Thanks to this table, we know that “:math:`1 < 2 + 3`” is a short way to write “:math:`1 < (2+3)`” and not “:math:`(1<2)+3`”, because :math:`+` has a higher precedence than :math:`<`. Grouping order, fixity in math ------------------------------ When we use the *same* operator two or more times, another question arises: should we group “:math:`1+2+3`” as “:math:`(1+2)+3`” or as “:math:`1+(2+3)`”? For the :math:`+` operator, this does not matter much, because addition is associative: we get the same value in either case. However, the situation is different with :math:`-`: we get different values for “:math:`1-2-3`” if we group like this: “:math:`(1-2)-3`” (equals -4) or like this: “:math:`1-(2-3)`” (equals 2). In math there are a couple of well known operators that are not associative: :math:`-`, :math:`\div` and exponentiation (:math:`(x^y)^z \neq x^{(y^z)}`). For this situation, in mathematics we nearly always choose for *left fixity*: when we use the same operator two or more times in a row, we start grouping from the left. This word “fixity” means “grouping order”. Predecence and associativity in programming =========================================== Like in math, nearly all programming languages have operator precedence rules that make it possible to omit parentheses in many cases. Most often, all operators in a programming language that represent a mathematical operation have a similar precedence as in math. However, there are also other programming operators than in math, so for every programming language you will need to have a look at its *operator precedence table*. For example, a part of the Java operator precedence table looks like this: ========== ============= Operator Precedence ========== ============= ``* / %`` 3 ``+ -`` 4 ``< >`` 6 ``==`` 7 ========== ============= Note the precedence level is sometimes represented, like in the table above, by a number where a lower number means a higher precedence. For example priority “1” may mean the operator binds tighter than all other operators with a larger priority number. As a rule of thumb, read the description of the table! Also, usually the highest precedence operators are listed first. In addition to precedence levels, programming languages also define a fixity for most operators. This is called *associativity* in the context of programming. For example we say that the operators ``+`` and ``*`` in Java are “left-associative” to mean that they are grouped from the left. The following links provide operator precedence tables for different languages. **Check them out and see where they overlap and where they differ.** - `Operator precedence in Java`__ .. __: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html - `Operator precedence in C++`__ .. __: http://en.cppreference.com/w/cpp/language/operator_precedence - `Operator precedence in Python`__ .. __: https://docs.python.org/3/reference/expressions.html#operator-precedence - `Operator precedence in R`__ .. __: http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Infix-and-prefix-operators - `Operator precedence in Matlab and Simulink`__ .. __: http://nl.mathworks.com/help/matlab/matlab_prog/operator-precedence.html Note in particular that some language place ordering comparison (``< >``) at the same level as the equality comparison, and others not. Right associativity =================== The reason why we need to care a bit more about associativity in programming than in math is that *some operators are right-associative*. For example, in Python, the arithmetic exponentiation noted ``**`` is right-associative: the expression “``2**3**4``” is really equivalent to “``2**(3**4)``”. (Java does not have an operator for this.) In Java (and other languages from its family including C and C++), there are two imporant constructs that are right-associative: assignment and ``if-else``. Right associativity of assignments ---------------------------------- The assignment in C, C++, Java and other languages is defined to be right-associative in order to simplify the assignment of multiple variables to the same value. So instead of writing:: x = 3; y = 3; z = 3; we can write:: x = y = z = 3; Which is equivalent to “``x = (y = (z = 3))``”. This works because the “result” of an assignment is the variable on the left of the equal sign. So “``z = 3``” sets ``z`` to the value 3 then gives ``z`` back into “``y = z``”, which changes ``y`` then gives ``y`` back to “``x = y``”. Of course all this would not work if the assignment was left-associative. Right associativity of ``if-else`` ---------------------------------- This is a dangerous pitfall which need particular attention. Consider the following program fragment: .. code:: java int x = 1; if (1 > 6) if (3 > 2) x = 2; else x = 3; What is the resulting value for ``x``? The proper answer is 1, not 3! This is because ``if-else`` is right-associative: the ``else`` part must be grouped with the first “``if``” found from the right. So the example above is really equivalent to: .. code:: java int x = 1; if (1 > 6) { if (3 > 2) x = 2; else x = 3; } Combined operators ================== Most programming language provide *combined operators* to shorten expressions. The most well-known are “``<=``” and “``>=``”, from mathematics. We can draw the following equivalence table: ============ ======================= Operation Equivalent to ============ ======================= ``a <= b`` ``(a < b) || (a == b)`` ``a >= b`` ``(a > b) || (a == b)`` ``a != b`` ``!(a == b)`` ============ ======================= Combined assignment and arithmetic ---------------------------------- In nearly all programming languages with an assignment operator, the following pattern happens often in code: ``=`` Where the same variable name is expressed on the left and right side of “``=``”. For example:: i = i + 1 a = a * 2 z = z - 3 Since this pattern is so common, most language will provide combined assignment operators of the form: = For example in Java, C and C++ the following equivalences hold: ============ ======================= Operation Equivalent to ============ ======================= ``a += b`` ``a = a + b`` ``a -= b`` ``a = a - b`` ``a /= b`` ``a = a / b`` ``a *= b`` ``a = a * b`` ``a %= b`` ``a = a % b`` ============ ======================= Pre- and Post- increment and decrement -------------------------------------- The C language, which Java inherits from, also has two additional operators: ``++`` and ``--``. They each exist in two forms: a *prefix* form “``++x``” and a *suffix* form “``x++``”, for a total of 4 operators. They are defined as follows: *Pre-increment and pre-decrement:* Syntax: ``++`` ``--`` Semantics: Equivalent respectively to “ ``+= 1``” and “ ``-= 1``”: the variable is incremented (resp. decremented) by 1, then the variable is returned as result into the enclosing expression. For example: .. code:: java int x = 42; int y = ++x; System.out.printf("%d %d\n", x, y); // prints 43 43 The prefix form is the simplest to understand at first contact, however in practice the suffix form is more commonly used: *Post-increment and post-decrement:* Syntax: ``++`` ``--`` Semantics: 1. the current value of the variable is saved. 2. the variable is incremented (resp. decremented) by 1. 3. the value saved in step #1 is returned as result into the enclosing expression. For example: .. code:: java int x = 42; int y = x++; System.out.printf("%d %d\n", x, y); // prints 43 42 The name “pre-increment” comes from Latin “pre” for “before”: the variable is incremented before its value is given back in the enclosing expression. In “post-increment” the variable is incremented “after” its value is given back in the enclosing expression. Important concepts ================== - *operator precedence*; - *fixity* in math and *associativity* in languages; - how to read a precedence table; - right associativity of assignments in Java; - right associativity of ``if-else`` in Java; - combined operators; - pre- and post- increment and decrement. Further reading =============== - Think Java, section 2.7 (pp. 19-20), section 8.8 (p. 97) - Introduction to Programming, section 2.5 (pp. 47-51) - Absolute Java, Appendix 2 (p. 1141), increment & decrement operators (pp. 30-33) ---- Copyright and licensing ======================= Copyright © 2014, Raphael ‘kena’ Poss. Permission is granted to distribute, reuse and modify this document according to the terms of the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit `http://creativecommons.org/licenses/by-sa/4.0/ `_.