#### Operators

The four basic arithmetic operators, **+**, **-**, *****, and **/**, can be used with any
integer or floating point type. (We'll learn about more advanced types, such
as fixed point types, later in the course.) The exponentiation operator, ******,
takes a base of type Integer or Float, and an exponent of type Integer. It
returns the same type as the base. (If the base is Integer, the exponent may
not be negative.)

In Ada 95, Float ** Float is part of the package **Numerics.Elementary_Functions;**
that package also provides Exp, Log, and the trigonometric functions. See
Annex A.5.1 in the Ada 95 RM for more details. Ada 83 compilers don't
necessarily provide these functions, but some do provide them in a math
package.

If we **with** and **use** a package containing Float ** Float, then our program can use ** between two Floats.

The six **relational operators** are these:

< | less than | > | greater than | = | equal to | ||

<= | less than or equal to | >= | greater than or equal to | /= | not equal to |

Five of these are the same as in Basic and Pascal, but the Ada symbol for "not
equal to" is **/=**, because **<>** means box. (We'll discuss the "box" further when
we cover array declarations and again when we cover generics.) The relational
operators compare two objects of the same type, and return a result of type
Boolean.

All of the above operators are used **between** two objects (e.g., **B := A + B;**).
Of course, **+** and **-** may also be **unary** operators (**B := +A; A := -A;**).

The operators **and**, **or**, and **xor** are used between two Boolean objects, and **not** is
a unary Boolean operator. Naturally, **xor** is the exclusive or: **A xor B** is True
if either A or B is True, but not if both are True.

The numeric operator **abs** takes the absolute value of an Integer or Float.
Since **abs** is a unary operator like **-**, we can write **B := abs A;**. We may, but
don't have to, use parentheses and write **B := abs(A);**.

When used between two integers, **/** gives only the integer part of the quotient.
Thus **11/4** is 2. The operators **mod** (modulo) and **rem** (remainder) are very
similar to each other, and are used between two integers to give only the
remainder in division. For example, **11 mod 4** is 3. For positive parameters,
mod and rem are the same. But with negative parameters, **mod** gives the sign of
the denominator while rem gives the sign of the numerator. Many programmers
simply ignore rem and use mod exclusively.

**&**concatenates arrays, so we'll discuss it later. We'll learn that a String is one type of array (an array of Characters), so

**&**can concatenate Strings.

#### Range Tests

The reserved word **in** tests if something is inside a range, and returns a
Boolean result. For example, if Lower, Upper, and X are declared as Floats, we
need not write

if X >= Lower and X <= Upper then ... end if;This can be expressed more clearly as

if X in Lower .. Upper then ... end if;

We can also write **not in**. Thus **X not in Lower .. Upper** is a clear way of expressing **X < Lower or X > Upper**.

A subtype may be substituted for the range to the right of **in**. If Day_Subtype is defined as a subtype of Integer, and I is an Integer, then we can write **I in Day_Subtype**.

#### Question

If we have the following declarations:B : Boolean; A, X, Y : Character;then which

**one**of the following is

**illegal**?

#### The Short Circuit Forms

Suppose that **N** (for numerator) and **D** (for denominator) are Floats, and we want
to execute a block of code if the quotient is 10.0 or greater. We could write

if N/D >= 10.0 then -----; -----; (block of code) -----; end if;However, we realize that if

**D**is 0.0, the program will raise a Constraint_Error or Numeric_Error trying to compute

**N/D**. If the denominator is zero, we consider the quotient to be very large, so we want to execute the block of code when

**D**is zero. Our second attempt might be

if D = 0.0 or N/D >= 10.0 then -----; -----; (block of code) -----; end if;

Here we **hope** that **N/D** won't be evaluated if **D** is zero.
We figure that the
compiler should be smart enough to know that if the expression before **or** is
True, then the whole expression must be True, so the expression to the right of
or needn't be evaluated. However, there's no guarantee that the compiler will
write code to skip the evaluation of the second expression when the first is
True. An optimizing compiler just might, for some unknown reason, even decide
that the expression on the right should be evaluated first.

However, with the form **or else**, Ada can bypass (or "short circuit") evaluating
the expression on the right when the one on the left is true:

if D = 0.0 or else N/D >= 10.0 then -----; -----; (block of code) -----; end if;

Ada guarantees that the expression to the left of **or else** will be evaluated
first. If this expression is True, the entire expression must be True, and
it's guaranteed that the second expression won't be evaluated. If the first
expression is False, then of course the second expression must be evaluated to
determine if the entire expression is True. Thus the code above will never try
to divide by zero. If **D** is zero, the expression on the left is True. The expression on the right won't be evaluated in that case.

There's another "short circuit" form called **and then**. If the expression to
the left of **and then** is False, the whole expression must be False, and the
expression on the right won't be evaluated. If the expression on the left is
True, then the expression on the right must be evaluated to determine the value
of the entire expression. Suppose this time that we want to execute a block of
code if N/D is **less than** 10.0. If the denominator is zero, we consider the quotient to be very large, and we don't want to execute the block of code in
that case. We can write the following:

if D /= 0.0 and then N/D < 10.0 then -----; -----; (block of code) -----; end if;

Again this protects us from trying to divide by zero. If **D** is zero, the
expression on the left is False. The second expression won't be evaluated in
that case.

After we discuss arrays, we'll see how the short circuit forms can prevent us from using out-of-range subscripts. And when we learn about access types, we'll see how the short circuit forms can keep us from dereferencing a null access object ("pointer"). That means trying to access "the object pointed to" when there's no such object.

Note that Ada's **and then** is similar to && in C and C++, and Ada's **or else** is similar to || in C and C++.

Remember, **and then** evaluates the second expression only if the first expression
is True; **or else** evaluates the second expression only if the first is False.

#### Question

Assume that**N**has been declared

**Float**, and that our program

**with**s and

**use**s a math package with a square root function called

**Sqrt**. Naturally, we don't want to call

**Sqrt**with a negative parameter. Which of the following would be more appropriate?

## No comments:

Post a Comment