NAME

contextPercent.pl - Context for entering percentages using %

DESCRIPTION

This file implements a context in which students can enter percentage values using %. There are a number of options that allow you to control the number of decimal places, and whether mathematical operations are allowed.

To use the context, put

loadMacros("contextPercent.pl");

at the top of your problem file, and then issue the

Context("Percent");

command to select the context. To create a Percent value, use

$m = Compute("10%");

or

$m = Percent(.1);

and so on. Both of these produce equivalent values (10%).

There are also three limited contexts that can be obtained using one of the following:

Context("LimitedPercent");
Context("LimitedPercent-strict");
Context("Percent-strict");

The Percent context allows you to use percentages rather freely within an expression. For example

Compute("10% + 20%");

would produce the same result as Compute("30%"), and so would either of

Compute("10% + .2");
Compute("(5+5)% + (2^2*ln(e**5))%");

In this way, n% is treated essentially as (n/100).

You can enforce more restrictive rules using the LimitedPercent or LimitedPercent-strict contexts. The first of these allows operations within the number that preceeds the percent sign, but does not allow you to combine percentages with real numbers or other percentages. In this way, (5+5)% is legal, but 5% + 5% is not.

The LimitedPercent-strict context disallows all computations, and only allows you to enter percentages as a single numeric constant followed by a percent sign.

Finally, the Percent-strict context allows you to combine percent values, but the numeric part of the percent must be a constant, not an expression. For example, 10% + 5% is allowed, but not (10+5)%.

As with all MathObjects, you obtain an answer checker for a Percent object via the cmp method, e.g.,

ANS($m->cmp);

There are a number of options that you can supply to control the details of the answer checker, listed below. These can also be set as flags within the Context so that they affect all Percent objects that you create. For example,

ANS($m->cmp(forceDecimals=>1));

or

Context()->flags->set(forceDecimals => 1);
ANS($m->cmp)

would both produce answer checkers for $m where the student would have to enter decimals that include any trailing zeros.

decimalPlaces => 1

This controls the number of decimal places to use in output of Percent objects, and the number that a student will be required to enter (when the appropriate flags are given, as described below). The tolerance is set by default to be .0005, so if you change the number of decimal places, you should change the tolerance to correspond to it (two more zeros than decimalPlaces). For example

Context()->flags->set(
    decimalPlaces => 2,
    tolerance => .00005,
);

The default value is 1 decimal place.

forceDecimals => 0

This value controls whether students are forced to enter the full number of decimals, even if there are trailing zeros. When set to 0 (the default for the Percent, Percent-strict, and LimitedPercent contexts), trailing zeros may be left off, so Compute("10.0%") could be entered as just 10% by a student. When set to 1 (the default for the LimitedPercent-strict context), if decimalPlaces is 2, then Compute("10.00%") would require the student to enter 10.00% rather than 10% or 10.0%. It really only makes sense to set this in the LimitedPercent-strict context, since in the other two, percent values can be computed, and so the number of decimal places is not really known.

noExtraDecimals => 0

This determines whether students are allowed to enter decimals beyond the number given by the decimalPlaces flag. If set to 0 (the default for the Percent, Percent-strict, and LimitedPercent contexts), any number of decimals are allowed (but the tolerance determines what values are meaningfull), while if set to 1 (the default for the LimitedPercent-strict context), students are not allowed to enter more than the required number of decimals and receive a warning if they do.

trimTrailingZeros => 1

This determines whether the output for Percent objects will have trailing zeros removed. When set to 1 (the default for the Percent, Percent-strict, and LimitedPercent contexts), if decimalPlaces is 2, then 10.00% will display as 10% and 10.30% will display as 10.3%. When set to 0 (the default for LimitedPercent-strict), trailing zeros will be retained, so the output will always have exactly decimalPlaces decimal values, even if they are zero.

promoteReals => 1

This determines whether real numbers can be combined and compared with percentages. When set to 1 (the default for the Percent context), students could enter Compute("10%") as either 10% or .1 or 5% + .05, while when set to 0 (the default for the Limited and strict contexts), students must enter percentages using the percent symbol (%).

strictPercent => 0

This controls whether the number preceding a percent sign can be a computation or whether it must be a numeric constant. When set to 0 (the default for the Percent and LimitedPercent contexts), students can use formulas to create a percentage value, e.g., (5 + 10)% for 15%. When set to 1 (the default for the Percent-strict and LimitedPercent-strict context), only numeric constants can be followed by the percent sign. Note that setting this flag to 1 also requires that you set reduceConstants and reduceConstantFunctions to 0 as well.

The default tolerance of .0005 works properly only if your original percent values have no more than 1 decimal place. If you were to do

$m = Compute("10.15%");

for example, then $m would print as 10.2%, but neither a student answer of 10.1% nor of 10.2% would be marked correct. That is because neither of these are less than .0005 away from the correct answer of 10.15% (remember that 10.15% is .1015). If you create percentages that have more decimal places than the usual one place, you may want to round or truncate them. Percent objects have two methods for accomplishing this: round() and truncate(), which produce rounded or truncated copies of the original Percent object:

$m = Compute("34.127%")->round;    # produces 34.13%
$m = Compute("34.127%")->truncate; # produces 34.12%

These are particularly helpful if you are producing percentages via computations.