# 7 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 6). 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 6 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 6, 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 6. 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):

[latex]b = 5.00 + 10.00 m + 6.25 h - 5.00 a - 161.00 \delta_f[/latex]

where [latex]b[/latex] denotes the BMR (in kilocalories per day), [latex]m[/latex] denotes the person’s mass (in kilograms), [latex]h[/latex] denotes the person’s height (in centimeters), [latex]a[/latex] denotes the person’s age (in years), and [latex]\delta_f[/latex] is [latex]1[/latex] if the person is female and [latex]0[/latex] 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 6, you might think that you should use `boolean`

variables, `if`

statements, and the updating pattern from Chapter 1 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 4 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 [latex]\{\texttt{1}, \texttt{2}, \ldots, \texttt{max}\}[/latex] it follows that `(value + max)`

is an element of the set [latex]\{\texttt{(1+max)}, \texttt{(2+max)}, \ldots, \texttt{(value+max)}\}[/latex]. 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 [latex][\texttt{0}, \texttt{max}][/latex], it follows that, as required, `(value / threshold)`

is `0`

when `value`

is less than `threshold`

and that it is in [latex][\texttt{1}, \texttt{max}][/latex] 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); }