9

Most languages such as Fortran, Python, Ruby, Perl, Awk,... define precedence of the exponentiation operator higher than that of the unary plus and minus. This creates the following results:

In [1]: -2**1
Out[1]: -2

In [2]: -2**2
Out[1]: -4

Shells suchs as Ksh, bash, zsh have the precedence of those two operators reversed. This leads to the surprising result:

$ echo $((-2**1))
-2
$ echo $((-2**2))
4

Question: Why do shells have this particular precedence order? I assume this is genealogical based ksh > bash > zsh. But still ..

Note: exponentiation is not part of POSIX

Note: other languages/interpreters exist with a similar precedence order such as bc, tcl


Related questions:

kvantour
  • 25,269
  • 4
  • 47
  • 72
  • 1
    Awk's ^ has a higher precedence than unary -/+ as well – oguz ismail Jun 25 '20 at 10:37
  • @oguzismail yes, I've added it to the list. There are probably many more languages that fit that picture as it is in line with the precedence that is used in written mathematics. Those shells seem to be the odd duck. – kvantour Jun 25 '20 at 10:49
  • 1
    It's worth noting that unary minus in written mathematics behaves the same as in Python. https://en.wikipedia.org/wiki/Order_of_operations#Unary_minus_sign – chepner Jun 25 '20 at 11:36
  • @oguzismail you seem to have removed the comment about `bc`, I was just going to read it :( – kvantour Jun 25 '20 at 13:59
  • @user1934428 agreed. Any place you would suggest? [retrocomputing.se] [softwareengineering.se] [unix.se] ... ? – kvantour Jun 25 '20 at 14:11
  • Unfortunately no. I have interest in evolution of programming language too, but my impression is that not many people share this interest. If you find a place where such historic stuff is discussed, let me know. – user1934428 Jun 25 '20 at 14:17

1 Answers1

6

According to Wikipedia, the mathematical convention is that unary minus has a lower precedence than exponentiation. Some programming languages follow this, others don't.

But the above article also gives examples of different conventions for mathematical notation used in scientific publications1; e.g. the precedence of different ways of writing multiplication and division.


You asked: Why?

Well, in most cases there isn't a clear rationale for why particular language designers made particular choices; see the answers to this Q&A. However, we certainly can't justify the position that any particular precedence system is "correct" from a theoretical stand-point.

In general, the guiding principles for PL precedence systems seem to be:

  • Try to be consistent with the ancestors for this language.
  • Try to be consistent with perceived mathematical convention.
  • Do what "feels right" at the time.

The results are not consistent.

Fortunately:

  1. people tend to get used to the quirks of the languages that they use most of the time, and

  2. the exponentiation operator is not used very often2, and even less often with unary minus.

So it doesn't usually matter. (Except when someone gets it wrong in a context that has huge impact / consequences. And even then, there should be processes in place to deal with human error.)


The operator precedence for expression evaluation in bash is documented as being based on C operator precedence. (See man bash.) C doesn't have an exponentiation operator, but it does make unary + and - higher precedence than multiplication and division.

So in order to be consistent with C, the bash implementors needed to put the operator precedence of ** above *, / and % and below unary -. (Putting ** above unary - goes against the clear intent of C ... which is that unary - is above all other arithmetic operators.)


If your real question is not "why did they do it" but "are the reasons documented", you will probably need to trawl through developer mailing lists, source code repositories and so on for clues. Or maybe try asking the designers ... though they may not remember the reasons accurately.


1 - If mathematicians can't be consistent about notation, why is it a big deal that programming language designers aren't either?

2 - Indeed, many programming languages don't even support an exponentiation operator.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216