###### Books / Patterns for Beginning Programmers / Chapter 9

# Indicator Methods

Sometimes the value needed to perform a calculation is known, and other times it too must be calculated. This is true of both “traditional” values and indicators (of the kind discussed in Chapter 8). This chapter considers problems in which an indicator’s value must be calculated before it can be used in another expression.

## Motivation

There’s a famous saying among performers, “the show must go on”, which
means that there must be a show whenever there’s an audience. In the
context of Chapter
8
on indicators, this means that the number of seats sold for a particular
showtime must be used to calculate an indicator, setting it to `0`

when
no tickets have been sold and setting it to `1`

otherwise. This is an
example of a *threshold indicator* in which the threshold is 1.

So, given that some number of tickets has been sold for a particular
show time, you must determine the number of shows that must be offered
at that time (i.e., either `0`

or `1`

). Letting `shows`

denote the
number of shows and `sold`

denote the number of tickets sold, you want
to calculate `shows`

from `sold`

in such a way that it takes on the
value `0`

when `sold`

is 0 and it takes on the value `1`

for all
positive values of `sold`

.

## Review

You could, of course, calculate the value of the variable `shows`

as
follows:

```
if (sold >= 1) {
shows = 1;
} else {
shows = 0;
}
```

However, you should also know that this is a bad practice, since it is likely that you will need to use this simple algorithm in more than one place. Hence, to avoid code duplication, you should instead write a method like the following:

```
public static int shows(int sold) {
if (sold >= 1) {
return 1;
} else {
return 0;
}
}
```

and use it as needed.

## The Pattern

The entertainment example is, obviously, a very particular problem.
However, it can easily be generalized to uncover a pattern. In
particular, the entertainment problem is a particular example of a
general problem in which you need to determine whether a particular
value exceeds a particular threshold. Further, there is an even more
general problem in which you need a method that returns a value of `0`

or `1`

based on the value of the parameters it is passed.

For threshold indicators, the solution to the problem is the following method:

```
public static int indicator(int value, int threshold) {
if (value >= threshold) {
return 1;
} else {
return 0;
}
}
```

For other indicators, the solution is a method with parameters that vary with the specifics of the problem.

## Examples

It’s useful to consider examples of both threshold indicators and other indicators.

### Threshold Indicators

Continuing with the entertainment example, the threshold is `1`

(i.e.,
if the size of the audience is 1 or more then there must be a show), so
given the size of the audience (represented by the variable `size`

), the
number of shows is given by the following:

```
shows = indicator(sold, 1);
```

Returning to the parking ticket example used in Chapter
8,
letting the number of prior tickets be given by `priors`

, the fine can
be calculated as follows:

```
baseFine = 10.00;
repeatOffenderPenalty = 35.00;
totalFine = baseFine + (indicator(priors, 1) * repeatOffenderPenalty);
```

It is also instructive to return to the car rental example from Chapter 8. For this example, you can initialize the necessary variables as follows:

```
baseRate = 19.95;
ageSurcharge = 10.00;
ageThreshold = 25;
multiSurcharge = 5.00;
multiThreshold = 1;
```

Then, you can calculate the daily rental rate as follows:

```
rate = baseRate
+ (1 - indicator(minimumAge, ageThreshold)) * ageSurcharge
+ indicator(extraDrivers, multiThreshold) * multiSurcharge;
```

Notice that, the age surcharge uses a converse threshold indicator while the multi-driver surcharge uses an ordinary threshold indicator.

### Other Indicators

As an example of a more general indicator, consider the following method for calculating a person’s basic metabolic rate (BMR):

\[b = 5.00 + 10.00 m + 6.25 h - 5.00 a - 161.00 \delta_f\]where \(b\) denotes the BMR (in kilocalories per day), \(m\) denotes the person’s mass (in kilograms), \(h\) denotes the person’s height (in centimeters), \(a\) denotes the person’s age (in years), and \(\delta_f\) is \(1\) if the person is female and \(0\) otherwise.

Now, suppose the `double`

variables `m`

, `h`

, and `a`

contain the values
of the person’s mass, height, and age (respectively), and the `String`

variable `s`

contains the person’s sex. Then, you would create the
following indicator method:

```
public static int indicator(char sex) {
if ((sex == 'F') || (sex == 'f')) {
return 1;
} else {
return 0;
}
}
```

and use it as follows:

```
b = 5.00 + 10.00 * m + 6.35 * h - 5.00 * a - 161.00 * indicator(s);
```

## Some Warnings

As in the discussion of indicator variables in Chapter
8,
you might think that you should use `boolean`

variables, `if`

statements, and the updating pattern from Chapter
2
instead of indicator methods. The trade-offs here are the same as the
trade-offs there.

It is also important to realize that you shouldn’t over-generalize the
code that is used in this pattern. Suppose, for example, you needed to
assign the value `true`

to the `boolean`

variable `isLegal`

if and only
if the value in the variable `age`

is greater than or equal to the value
in the “constant” `DRINKING_AGE`

. Given the code used to implement the
pattern, you might be tempted to do something like the following.

```
if (age >= DRINKING_AGE) {
isLegal = true;
} else {
isLegal = false;
}
```

However, most people think this is completely inappropriate (and
demonstrates a lack of understanding of relational operators and
`boolean`

variables). Instead, it should be implemented as follows:

```
isLegal = (age >= DRINKING_AGE);
```

That is, the expression `(age >= DRINKING_AGE)`

evaluates to a `boolean`

that should be directly assigned to the variable `isLegal`

— the `if`

statement is superfluous. In other words, a pattern that is appropriate
for assigning values to numeric variables or returning numeric values
(like those in the previous section) may not be appropriate for
`boolean`

variables.

### Looking Ahead

On some hardware architectures, `if`

statements (including the `boolean`

expressions that must be evaluated) take more CPU time to execute than
arithmetic operations. Hence, on such architectures it is important to
replace `if`

statements with arithmetic expressions. Threshold
indicators are an example of this that might arise in a course on
computer architecture.

If you’ve read Chapter
5
on arithmetic on the circle, you’re may be thinking about how you can
use the integer division operator and/or the remainder operator to
eliminate the `if`

statements. While it is, indeed, possible to do so,
the solution is not obvious. Consider the following candidates:

`(value / (max + 1))`

is`0`

when`value`

is`0`

, it is also`0`

for every other possible`int`

.`(value / max)`

is slightly better since it is`0`

when`value`

is`0`

, and`1`

when`value`

is`max`

, but it is still`0`

for every other possible`int`

.`value % (max + 1)`

is`0`

when`value`

is`0`

, and is`1`

when`value`

is`1`

, it is`value`

(not`1`

) otherwise. (Using`max`

rather than`(max + 1)`

in the denominator does not improve things.)

The easiest way to think about a solution that does work is to consider
the problem in three stages. First, consider the case when the threshold
is less than twice the value. Then, consider the special case of a
non-zero threshold indicator (i.e., when the threshold is `1`

). Finally,
consider the general case (i.e., the threshold can be anything).

### A Threshold Less Than Twice the Value

When `value`

is strictly less than `(2 * threshold)`

, it follows that
`(value / threshold)`

is going to be either `0`

or `1`

(because, using
real division, the result will always be less than `2`

). Hence, in this
case, you can find the `indicator`

as follows:

```
indicator = (value / threshold);
```

Unfortunately, this won’t work in general because we don’t always know
`value`

.

### A Threshold of 1

One way to get to the correct solution to the special case when the
threshold is `1`

is to find `max`

consecutive integers that have the
property that each divided by some value is `1`

.

To move in the right direction, observe that for `value`

in the set
\(\\{\texttt{1}, \texttt{2}, \ldots, \texttt{max}\\}\) it
follows that `(value + max)`

is an element of the set
\(\\{\texttt{(1+max)}, \texttt{(2+max)}, \ldots,
\texttt{(value+max)}\\}\). Since `value`

is less than or equal
to `max`

, it also follows that each element of this set is less than or
equal to `(2*max)`

. Hence, the result of dividing each element by
`(max+1)`

(using integer division) is `1`

(because using real division
the result would be strictly between `1`

and `2`

).

To finalize the pattern when the threshold is `1`

, observe that
`(0 + max) / (max + 1)`

is `0`

(using integer division), since the
numerator is strictly less than the denominator. What this means is that
the pattern when the threshold is `1`

can be expressed as the following
non-zero indicator:

```
indicatorNZ = (value + max) / (max + 1);
```

### The General Case

In the general case, you need to create an indicator that is `0`

when a
non-negative `value`

is less some `threshold`

and `1`

otherwise. The
easiest way to create such an indicator is to first calculate an
intermediate value that is `0`

when the `value`

is less than the
`threshold`

and positive otherwise, and then use a non-zero indicator.

To do so, observe that, since both `value`

and `threshold`

are in the
interval \(\[\texttt{0}, \texttt{max}\]\), it follows
that, as required, `(value / threshold)`

is `0`

when `value`

is less
than `threshold`

and that it is in \(\[\texttt{1},
\texttt{max}\]\) otherwise. Hence, you can calculate
`intermediate`

as follows:

```
intermediate = value / threshold;
```

Then, you can use `intermediate`

and the expression for a non-zero
indicator to calculate a threshold indicator as follows:

```
indicatorT = (intermediate + max) / (max + 1);
```

Putting it all together yields the following general expression for a threshold indicator:

```
indicatorT = ((value / threshold) + max) / (max + 1);
```

To see that this is, indeed, a generalization of the special case, you
need only substitute `1`

for `threshold`

in this expression.

This leads to a general-purpose method like the following for
calculating the threshold indicator without an `if`

statement:

```
public static int aindicator(int value, int threshold, int max) {
return ((value / threshold) + max) / (max + 1);
}
```