Further example:
echo ' 3 ^ 4 ' | bc
echo ' - 3 ^ 4 ' | bc
echo ' - - 3 ^ 4 ' | bc
all output
81, because the negation operator
- has higher precedence in bc than the exponentiation operator
^ .
That is, the above expressions are equivalent to
echo ' 3 ^ 4 ' | bc
echo ' (-3)^4 ' | bc
echo ' (-(-3))^4 ' | bc
Similarly for Bash,
bash -c 'echo $[-3**4]',
bash -c 'echo $[--3**4]', and
bash -c 'echo $[---3**4]' all output
81 . (The same with
bash -c 'echo $(( -3**4 ))' and so on, for the same reason.)
This is explained in their documentation by stating that the negation operator
- has higher precedence than the exponentiation operator (
^ in bc,
** in Bash), which has higher precedence than subtraction (
-).
However, Python, Perl, and Ruby all parse/associate the expressions correctly:
python -c 'print(-3**4)'
perl -E 'say -3**4'
ruby -e 'puts -3**4'
all output
-81.
Their documentation, fortunately, clearly says that exponentiation
** has higher precedence than negation
- . (Note, however, that they do have slightly different operator precedences from each other, so expressions in one are not necessarily parsed the exact same way in the other. Trap for young players!)
In general, because many programmers aren't
that good at math and changing the precedence/associativity rules when your users have gotten used to them would be downright evil, one must assume that software environments do not always parse or compute expressions correctly. However, they can almost always be forced to Do The Right Thing, by using parentheses.
(It would be better if there was a separate operators for negation and subtraction instead. I wouldn't mind a superscript minus,
-, myself. It would completely remove the ambiquity. Similarly for exclusive-or/exponentiation (
^). I blame ASCII for not having suitable glyphs to port to the
Portable Character Set.
In all the above environments and languages, adding parentheses will fix the issue:
-(3**4) or
-(3^4) (depending on what is used to signify exponentiation) will yield the expected answer,
-81.
TL;DR: Consider it a human interface problem in various applications and programming languages. Always use parentheses to avoid mistakes.