Power of Operators |
Written by Harry Fairhead | ||||
Thursday, 28 January 2021 | ||||
Page 2 of 3
Reverse PolishA better, but less familiar, notation is reverse Polish where the operator is written after its operands. For example, AB+ is reverse Polish for A+B. The advantage of reverse Polish is that it does generalize to n-adic operators. For example, ABC@ is a reverse Polish expression using the triadic operator that finds the maximum of A,B and C. Reverse Polish has another advantage in that operator priorities can be represented by the order that they occur. For example, AB+C* is clearly (A+B)*C because the multiplication cannot be evaluated until the addition is evaluated to provide the second operand for the multiplication. Because an operator can look like a function it is possible to confuse the two. For example, in Ada abs, i.e. taking the absolute value of a quantity, is an operator but in Pascal and most other languages it is a function. If you don't notice this subtle difference you could end up writing expressions in Ada or Pascal that don't work as you expect. As well as not agreeing about whether something is an operator or a function languages don't always agree about the assignment of priorities and if you switch languages this can be a cause of serious and difficult to find bugs. For example, Fortran and BASIC give the exponentiation operator ^ the highest precedence but most spreadsheets give it second place to the unitary minus -. It isn't even always reasonable to stick to a simple precedence rule in all cases. For example, in many languages the exponentiation operation has the highest precedence of all operators and in general this is reasonable but consider
using the strict precedence this should be
i.e. -16 but this clearly isn't what the programmer intended. To put things right many languages alter the priority of exponentiation when it is immediately followed by negation. That is 4^-2 is evaluated as 4 raised to the power of -2 (i.e. 1/16). Operators and expressions are powerful and compact ways of writing programs and many languages cannot resist the temptation to use them for nearly everything. The most often quoted example of an operator based language is APL but surprisingly it doesn't use an operator precedence at all and simply evaluates everything left to right!
Operators in CIn my opinion the operator king of modern languages is C and its approach has been inherited by many of the languages that are based on it. C has a range of operators that needs 16 levels of precedence to control! This bewildering array of operators is one of the reasons why C is intimating to the beginner and can look cryptic if written using lots of operators. Once you start to extend the range of operators that a language has then you have to worry about associativity as well as precedence. Associativity is simply the order that operators of the same priority will be evaluated. If you restrict your attention to simple arithmetic operators then the associativity isn't a problem because (A+B)+C is the same as A+(B+C). However when you move on to consider more general operators it does matter. For example, in C and many other languages (C# for example) the right shift operator A>>B shifts A right by B bits and
which means shift A right by B+C isn't the same as
shift A right by the result of the right shift of B by C bits. To make the result of such operations unambiguous C defines each operator as associating left to right or right to left i.e. right or left associative. The >> operator associates left to right because this means that A>>B>>C is (A>>B)>>C and this is the same as A>>(B+C).
|
||||
Last Updated ( Thursday, 28 January 2021 ) |