# PGnumericevaluators.pl - Macros that generate numeric answer evaluators.

### From WeBWorK

# NAME

PGnumericevaluators.pl - Macros that generate numeric answer evaluators.

# SYNOPSIS

ANS(num_cmp($answer_or_answer_array_ref, %options_hash)); ANS(std_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(std_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(std_num_cmp_list($relTol, $format, @answerList)); ANS(std_num_cmp_abs_list($absTol, $format, @answerList)); ANS(arith_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(arith_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(arith_num_cmp_list($relTol, $format, @answerList)); ANS(arith_num_cmp_abs_list($absTol, $format, @answerList)); ANS(strict_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(strict_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(strict_num_cmp_list($relTol, $format, @answerList)); ANS(strict_num_cmp_abs_list($absTol, $format, @answerList)); ANS(frac_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(frac_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(frac_num_cmp_list($relTol, $format, @answerList)); ANS(frac_num_cmp_abs_list($absTol, $format, @answerList));

# DESCRIPTION

Numeric answer evaluators take in a numerical answer, compare it to the correct answer, and return a score. In addition, they can choose to accept or reject an answer based on its format, closeness to the correct answer, and other criteria.

The general numeric answer evaluator is `num_cmp()`

. It takes a hash of named
options as parameters. There are also sixteen specific "mode"_num_cmp() answer
evaluators for use in common situations which feature a simplified syntax.

## MathObjects and answer evaluators

The MathObjects system provides $obj->`cmp()`

methods that produce answer
evaluators for a wide variety of answer types. `num_cmp()`

has been rewritten to
use the appropriate MathObject to produce the answer evaluator. It is
recommended that you use the MathObjects `cmp()`

methods directly if possible.

# num_cmp

ANS(num_cmp($answer_or_answer_array_ref, %options));

`num_cmp()`

returns one or more answer evaluators (subroutine references) that
compare the student's answer to a numeric value. Evaluation options are
specified as items in the %options hash. This can make for more readable code
than using the "mode"_num_cmp() style, but some people find one or the other
easier to remember.

## Options

$answer_or_answer_array_ref can either be a scalar containing a numeric value or
a reference to an array of numeric scalars. If multiple answers are provided,
`num_cmp()`

will return a list of answer evaluators, one for each answer
specified. %options is a hash containing options that affect the way the
comparison is performed. All hash items are optional. Allowed options are:

**mode**-
This determines the allowable methods for entering an answer. Answers which do not meet this requirement will be graded as incorrect, regardless of their numerical value. The recognized modes are:

**std (default)**-
The default mode allows any expression which evaluates to a number, including those using elementary functions like

`sin()`

and`exp()`

, as well as the operations of arithmetic (+, -, *, /, and ^). **strict**-
Only decimal numbers are allowed.

**frac**-
Only whole numbers and fractions are allowed.

**arith**-
Arithmetic expressions are allowed, but no functions.

Note that all modes allow the use of "pi" and "e" as constants, and also the use of "E" to represent scientific notation.

**format**-
The format to use when displaying the correct and submitted answers. This has no effect on how answers are evaluated; it is only for cosmetic purposes. The formatting syntax is the same as Perl uses for the

`sprintf()`

function. Format strings are of the form '%m.nx' or '%m.nx#', where m and n are described below, and x is a formatter.Esentially, m is the minimum length of the field (make this negative to left-justify). Note that the decimal point counts as a character when determining the field width. If m begins with a zero, the number will be padded with zeros instead of spaces to fit the field.

The precision specifier (n) works differently depending on which formatter you are using. For d, i, o, u, x and X formatters (non-floating point formatters), n is the minimum number of digits to display. For e and f, it is the number of digits that appear after the decimal point (extra digits will be rounded; insufficient digits will be padded with spaces--see '#' below). For g, it is the number of significant digits to display.

The full list of formatters can be found in the manpage for

`printf(3)`

, or by typing "perldoc -f sprintf" at a terminal prompt. The following is a brief summary of the most frequent formatters:%d decimal number %ld long decimal number %u unsigned decimal number %lu long unsigned decimal number %x hexadecimal number %o octal number %e floating point number in scientific notation %f floating point number %g either %e or %f, whichever takes less space

Technically, %g will use %e if the exponent is less than -4 or greater than or equal to the precision. Trailing zeros are removed in this mode.

If the format string ends in '#', trailing zeros will be removed in the decimal part. Note that this is not a standard syntax; it is handled internally by WeBWorK and not by Perl (although this should not be a concern to end users). The default format is '%0.5f#', which displays as a floating point number with 5 digits of precision and no trailing zeros. Other useful format strings might be '%0.2f' for displaying dollar amounts, or '%010d' to display an integer with leading zeros. Setting format to an empty string ( '' ) means no formatting will be used; this will show 'arbitrary' precision floating points.

**tol**-
An absolute tolerance value. The student answer must be a fixed distance from the correct answer to qualify. For example, an absolute tolerance of 5 means that any number which is +-5 of the correct answer qualifies as correct. abstol is accepted as a synonym for tol.

**relTol**-
A relative tolerance. Relative tolerances are given in percentages. A relative tolerance of 1 indicates that the student answer must be within 1% of the correct answer to qualify as correct. In other words, a student answer is correct when

abs(studentAnswer - correctAnswer) <= abs(.01*relTol*correctAnswer)

tol and relTol are mutually exclusive. reltol is also accpeted as a synonym for relTol.

**zeroLevel, zeroLevelTol**-
zeroLevel and zeroLevelTol specify a alternative absolute tolerance to use when the correct answer is very close to zero.

If the correct answer has an absolute value less than or equal to zeroLevel, then the student answer must be, in absolute terms, within zeroLevelTol of correctAnswer, i.e.,

abs(studentAnswer - correctAnswer) <= zeroLevelTol

In other words, if the correct answer is very near zero, an absolute tolerance will be used. One must do this to handle floating point answers very near zero, because of the inaccuracy of floating point arithmetic. However, the default values are almost always adequate.

**units**-
A string representing the units of the correct answer. If specified, the student answer must include these units. The strings and units options are mutually exclusive.

**strings**-
A reference to an array of strings which are valid (but incorrect) answers. This prevents non-numeric entries like "NaN" or "None" from causing a syntax error. The strings and units options are mutually exclusive.

**debug**-
If set to 1, extra debugging information will be output.

## Examples

# correct answer is 5, using defaults for all options num_cmp(5);

# correct answers are 5, 6, and 7, using defaults for all options num_cmp([5,6,7]);

# correct answer is 5, mode is strict num_cmp(5, mode=>'strict');

# correct answers are 5 and 6, both with 5% relative tolerance num_cmp([5,6], relTol=>5);

# correct answer is 6, "Inf", "Minf", and "NaN" recognized as valid, but # incorrect answers. num_cmp(6, strings=>["Inf", "Minf", "NaN"]);

# correct answer is "-INF", "INF" and numerical expressions recognized as # valid, but incorrect answers. num_cmp("-INF", strings => ["INF", "-INF"]);

# "mode"_num_cmp() functions

There are 16 functions that provide simplified interfaces to `num_cmp()`

. They are
organized into four groups, based on the number of answers accpeted (single or
list) and whether relative or absolute tolerances are used. Each group contains
four functions, one for each evaluation mode. See the mode option to `num_cmp()`

above for details about each mode.

GROUP:| "normal" | "list" | "abs" | "abs_list" | | single answer | list of answers | single answer | list of answers | MODE: | relative tol. | relative tolerance | absolute tolerance | absolute tolerance | -------+----------------+---------------------+--------------------+-------------------------+ std | std_num_cmp | std_num_cmp_list | std_num_cmp_abs | std_num_cmp_abs_list | frac | frac_num_cmp | frac_num_cmp_list | frac_num_cmp_abs | frac_num_cmp_abs_list | strict | strict_num_cmp | strict_num_cmp_list | strict_num_cmp_abs | strict_num_cmp_abs_list | arith | arith_num_cmp | arith_num_cmp_list | arith_num_cmp_abs | arith_num_cmp_abs_list |

The functions in each group take the same arguments.

## The normal group

ANS(std_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(arith_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(strict_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); ANS(frac_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol));

This group of functions produces answer evaluators for a single correct answer
using relative tolerances. The first argument, $correctAnswer, is required. The
rest are optional. The arguments are equivalent to the identically-named options
to `num_cmp()`

, above.

## The list group

ANS(std_num_cmp_list($relTol, $format, @answerList)); ANS(arith_num_cmp_list($relTol, $format, @answerList)); ANS(strict_num_cmp_list($relTol, $format, @answerList)); ANS(frac_num_cmp_list($relTol, $format, @answerList));

This group of functions produces answer evaluators for a list of correct answers
using relative tolerances. $relTol and $format are equivelent to the
identically-named options to `num_cmp()`

above. @answerList must contain one or
more correct answers. A list of answer evaluators is returned, one for each
answer provided in @answerList. All answer returned evaluators will use the
relative tolerance and format specified.

## The abs group

ANS(std_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(arith_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(strict_num_cmp_abs($correctAnswer, $absTol, $format)); ANS(frac_num_cmp_abs($correctAnswer, $absTol, $format));

This group of functions produces answer evaluators for a single correct answer
using absolute tolerances. The first argument, $correctAnswer, is required. The
rest are optional. The arguments are equivalent to the identically-named options
to `num_cmp()`

, above.

## The abs_list group

ANS(std_num_cmp_abs_list($absTol, $format, @answerList)); ANS(arith_num_cmp_abs_list($absTol, $format, @answerList)); ANS(strict_num_cmp_abs_list($absTol, $format, @answerList)); ANS(frac_num_cmp_abs_list($absTol, $format, @answerList));

This group of functions produces answer evaluators for a list of correct answers
using absolute tolerances. $absTol and $format are equivelent to the
identically-named options to `num_cmp()`

above. @answerList must contain one or
more correct answers. A list of answer evaluators is returned, one for each
answer provided in @answerList. All answer returned evaluators will use the
absolute tolerance and format specified.

## Examples

# The student answer must be a number in decimal or scientific notation # which is within .1 percent of 3.14159. This assumes # $numRelPercentTolDefault has been set to .1. ANS(strict_num_cmp(3.14159));

# The student answer must be a number within .01 percent of $answer (e.g. # 3.14159 if $answer is 3.14159 or $answer is "pi" or $answer is 4*atan(1)). ANS(strict_num_cmp($answer, .01));

# The student answer can be a number or fraction, e.g. 2/3. ANS(frac_num_cmp($answer)); # or ANS(frac_num_cmp($answer, .01));

# The student answer can be an arithmetic expression, e.g. (2+3)/7-2^.5 . ANS(arith_num_cmp($answer)); # or ANS(arith_num_cmp($answer, .01));

# The student answer can contain elementary functions, e.g. sin(.3+pi/2) ANS(std_num_cmp($answer)); # or ANS(std_num_cmp( $answer, .01));

# Miscellaneous functions

## [DEPRECATED] numerical_compare_with_units

ANS(numerical_compare_with_units($correct_ans_with_units, %options))

This function is deprecated. Use num_cmp with the units option instead:

ANS(num_cmp($correct_ans, units=>$units));

## [DEPRECATED] `std_num_str_cmp()`

ANS(std_num_str_cmp($correctAnswer, $ra_legalStrings, $relTol, $format, $zeroLevel, $zeroLevelTol))

This function is deprecated. Use `num_cmp()`

with the strings option instead:

ANS(num_cmp($correctAnswer, strings=>$ra_legalStrings, ...));

# SEE ALSO

the PGanswermacros.pl manpage, *MathObjects*.