# 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.