Ada Exponentiation surprises


Among all the languages I know, Ada is one of the few that offers and exponential operator: **.

In mathematics, you generally write an exponential using a small font and moving the exponent up above the normal line. The notation of x power y is written this way:

xy               (1)

I will assume that most people know that a negative number power an odd number is negative. The same negative number power an even number is positive. So for instance, -1 power 3 is -1 and -1 power 2 is 1:

-13 = -1    and    -12 = 1                 (2)

In Ada, you write such expression using the ** operator as in:

r := x ** y;                   (3)

So it would feel reasonable to write the expression:

r := -1 ** 3;                (4)

and expect r to be set to -1. And it is.

Similarly, you probably would think that the following will return 1:

r := -1 ** 2;                   (5)

And that's not the case. The result of this last expression is -1. Why? Because the minus is taken as a negation of a term and not a primary expression. In other words, the expression in (5) is equivalent to this one:

r := -(1 ** 2);                (6)

This can be disturbing since writing the expression with variables, the effects feel like they are different:

procedure test is                              (7)
  x, y, r: integer;
  x := -1;
  y := 2;
  r := x ** y;
end test;

 In this case r is set to 1. This is because when -1 is in variable x the expression becomes similar to this:

r := (-1) ** 2;                                      (8)

If you come from a language such as C/C++, Java, PHP, then you probably will expect (5) to work like (8). This is because in these languages the negate operator (-expr) is viewed as a primary operator.

Reference: RM 2005 Chapter 4.4 § 4