Enough stories, time for a new rule. Which is to always use parentheses in all except the simplest of math expressions. Languages have a precedence protocol, so the compiler can figure it out, but human readers may be confused.
As always, the underlying motivation involves code clarity for other humans reading the source code — the most important rule of all.
Sometimes there are news stories about math problems that people are puzzling, or even arguing, over. Often these involve the precedence protocol — the implicit order of math operations. This protocol removes ambiguity in an expression.
For example, consider the following expression:
2 + 5 * 3 + 4
This can evaluate to four values depending on the order of operations:
- 25 (((2+5)*3)+4)
- 49 ((2+5)*(3+4))
- 37 (2+(5*(3+4)))
- 21 (2+((5*3)+4)) or ((2+(5*3))+4)
The precedence protocol specifies an order of operations. One issue is that there are different protocols, but most of them (if not all) specify that multiplication (and division) should be done before addition (and subtraction).
So the proper evaluation of the equation is:
2 + (5 * 3) + 4 = 2 + 15 + 4 = 21
(The precedence on the multiple adds doesn’t matter, because addition is associative, but typically in such a case the order is left-to-right.)
If you were a math student in the USA, you might have learned the PEMDAS mnemonic to help remember the order of operations: Parentheses, Exponents, Multiplication/Division, Addition/Subtraction.
It’s important to pay attention to the implied equality between multiplication and division and between addition and subtraction. Consider:
10 – 3 + 2
Addition and subtraction have the same precedence, so evaluation defaults to left-to-right. The proper value is 9, not 5.
This is great and works just fine. If you can remember the rules (hence the mnemonic).
But when it comes to coding, different languages may have slightly different precedence rules, so you have to remember the language’s rules when writing expressions. And you have to be sure not to confuse those rules with the general arithmetic rules or with the rules of some other language.
More importantly, this applies to everyone who reads the code in the future.
On top of that, what if you remember the rules wrong and write an expression you think is doing one thing, but it’s really doing another. Will you catch the error?
As an aside, this issue applies to infix notation, which need needs parentheses or precedence to resolve order of operation ambiguities. But pre-fix and post-fix notation don’t suffer from the ambiguities.
Assuming the multiplication first, we’d write the first equation using pre-fix notation above as:
+ + 2 * 5 3 4
Which is actually a little more confusing than it needs to be. A slightly clearer way to write it is:
+ * 5 3 + 2 5
Well, maybe not that much clearer; pre-fix notation takes some getting used to (although I have a soft spot for it). It may seem more familiar if the operators are replaced by functions, like this:
In post-fix it would be:
2 5 3 * + 4 +
This is the protocol used in some electronic calculators and is a little easier to grasp. There is no ambiguity in either case.
So get in the good habit of always using parentheses in all but the very simplest expressions. Generally speaking this means any expression with more than one operator, but almost certainly those with more than two.
Everyone may know the right order for:
a * b + c * d
(a * b) + (c * d)
Because of course multiplication is first, but don’t the parentheses help the eye see immediately what’s going on? There is no burden on the reader to think about what was meant here.
In particular, the reader doesn’t have to question whether the writer knew for sure what they were doing. The parentheses make it clear for all involved.
Depending on implicit rules is almost always a Very Bad Idea. You can rarely, if ever, get in trouble being explicit (at least in coding).
Because sometimes that reader is you.