Forum archive 2000-2006

Michael Gage - PG answer evaluators

Michael Gage - PG answer evaluators

by Arnold Pizer -
Number of replies: 0
inactiveTopicPG answer evaluators topic started 4/27/2000; 6:51:25 PM
last post 6/29/2000; 10:32:42 AM
userMichael Gage - PG answer evaluators  blueArrow
4/27/2000; 6:51:25 PM (reads: 4678, responses: 3)

Answer Evaluating Functions

 

 

How to use them

 

Numerical compare:

  • ANS( strict_num_cmp( 3.14159 ) ); The student's 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( $answer,.01 ) ); The student's 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( frac_num_cmp( $answer) ) or ANS( frac_num_cmp( $answer,.01 )); The student's answer can be a number or fraction, e.g. 2/3.
  • ANS( arith_num_cmp( $answer) ) or ANS( arith_num_cmp( $answer,.01 )); The student's answer can be an arithmetic expression, e.g. (2+3)/7-2^.5 .
  • ANS( std_num_cmp( $answer) ) or ANS( std_num_cmp( $answer,.01 )); The student's answer can contain elementary functions, e.g. sin(.3+pi/2)
  • You can also specify additional parameters for controling the format of printed answers and for how answers close to zero are handled. Further, there are versions which use a fixed absolute tolerance rather than a relative percent tolerance. Finally, there are versions which will accept a list of answers. Also num_cmp( ) is an alias for std_num_cmp( ). See standard Answer Evaluating Functions.

(see also num_cmp)

 

String compare:

All the string comparison operators ignore initial and trailing white space.

  • ANS( std_str_cmp( "W. Mozart" ) ); Accepts "W. Mozart", "W. MOZarT" and so forth. Case insensitive. All internal spaces treated as single spaces.
  • ANS( std_cs_str_cmp( "Mozart" ) ); Rejects "mozart". Same as std_str_cmp but case sensitive.
  • ANS( strict_str_cmp( "W. Mozart" ) ); Accepts only the exact string.
  • ANS( unordered_str_cmp( "ABC" ) ); Accepts "a c B", "CBA" and so forth. Unordered, case insensitive, spaces ignored.
  • ANS( unordered_cs_str_cmp( "ABC" ) ); Rejects "abc". Same as unordered_str_cmp but case sensitive.
  • ANS( ordered_str_cmp( "ABC" ) ); Accepts "a b C", "A B C" and so forth. Ordered, case insensitive, spaces ignored.
  • ANS( ordered_cs_str_cmp( "ABC" ) ); Rejects "abc", accepts "A BC" and so forth. Same as ordered_str_cmp but case sensitive.
  • There are versions which will accept a list of answers. See standard Answer Evaluating Functions.
(see also str_cmp)

 

Function compare:

  • ANS( function_cmp( "cos(x)" ) ); Accepts cos(x), sin(x+pi/2), sin(x)^2 + cos(x) + cos(x)^2 -1, etc. This assumes $functVarDefault has been set to "x".
  • ANS( function_cmp( $answer, "t" ) ); Assuming $answer is "cos(t)", accepts cos(t), etc.
  • ANS( function_cmp_up_to_constant( "cos(x)" ) ); Accepts any antiderivative of sin(x), e.g. cos(x) + 5.
  • ANS( function_cmp_up_to_constant( "cos(z)", "z" ) ); Accepts any antiderivative of sin(z), e.g. sin(z+pi/2) + 5.
  • Further, there are versions which use a fixed absolute tolerance rather than a relative percent tolerance. You can also specify additional parameters. See standard Answer Evaluating Functions.

     

(see also fun_cmp for another syntax)

 

What are they?

They extend the ability of the instructor to check a student's answer. Instead of just providing a correct answer, they provide a function which evaluates the student's answer to determine if it is correct. In other words the instructor can control both the correct answer and a method for comparing it with the student's answer. Of course for many questions you can use the standard methods listed above. For details on the standard Answer Evaluating Functions see standard Answer Evaluating Functions. For details on writing your own Answer Evaluating Functions see writing your own Answer Evaluating Functions.

 

 

Details on using the standard Answer Evaluating Functions

Numerical compare:

  strict_num_cmp($correctAnswer); OR strict_num_cmp($correctAnswer,$relpercentTol); OR strict_num_cmp($correctAnswer,$relpercentTol,$format); OR strict_num_cmp($correctAnswer,$relpercentTol,$format,$zeroLevel); OR strict_num_cmp($correctAnswer,$relpercentTol,$format,$zeroLevel,$zeroLevelTol);

If not explicitly given, the various parameters have defaults which are defined in the Global.pm file or the individual course webworkCourse.ph file. Typically $relpercentTol defaults to .1, $format defaults to "", $zeroLevel defaults to 1E-14, and $zeroLevelTol defaults to 1E-12.
The student's answer must be a number (in integer, decimal, or scientific notation or e or pi) which is within $relpercentTol percent of $correctAnswer (i.e., abs($studentAnswer - $correctAnswer) <= abs(.01*$relpercentTol*$correctAnswer)). However, if the $correctAnswer has absolute value less than or equal to $zeroLevel, then the student's answer must be, in absolute terms, within $zeroLevelTol of $correctAnswer (i.e. abs($studentAnswer - $correctAnswer) <= $zeroLevelTol). One must do this to handle floating point answers equal to or near zero. The $format is passed to the prfmt printing routine defined in PGansweracros.pl and must be either a format suitable for sprintf, e.g. "%1.10g" , or "".

 

frac_num_cmp($correctAnswer); OR frac_num_cmp($correctAnswer,$relpercentTol); etc.

The possible parameters are the same as for strict_num_cmp and have the same defaults.
Similar to strict_num_cmp except that the student's answer can be a number or a fraction e.g. 2.1, 2/3, or 2.5/3.1, e, or pi/2. Syntax and arithmetic errors are reported to the student.

 

arith_num_cmp($correctAnswer); etc.

The possible parameters are the same as for strict_num_cmp and have the same defaults.
Similar to frac_num_cmp except that the student's answer can be an arithmetic expression containing +, -, *, /, ^ or *, (, ), e, and pi e.g. (2+3)/7-2^.5 . Syntax and arithmetic errors are reported to the student.

 

std_num_cmp($correctAnswer); etc.

The possible parameters are the same as for strict_num_cmp and have the same defaults.
Similar to arith_num_cmp except that the student's answer can also contain elementary functions and constants pi and e. For example sin(pi/2)+ ln(e) is a complicated way to write the number 2. Allowed functions are listed in "acceptable math functions". Syntax, arithmetic, and other errors are reported to the student. num_cmp is a short name for std_num_cmp.

 

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

These are the same as the above except that the student's answer must be within $absTol of $correctAnswer (i.e. abs($studentAnswer - $correctAnswer) <= $absTol). If not explicitly given, the parameters $absTol and $format have same defaults as in strict_num_cmp

 

strict_num_cmp_list($relpercentTol,$format,@answerList); strict_num_cmp_abs_list($absTol,$format,@answerList); frac_num_cmp_list($relpercentTol,$format,@answerList); frac_num_cmp_abs_list($absTol,$format,@answerList); arith_num_cmp_list($relpercentTol,$format,@answerList); arith_num_cmp_abs_list($absTol,$format,@answerList); std_num_cmp_list($relpercentTol,$format,@answerList); std_num_cmp_abs_list($absTol,$format,@answerList);

These are versions which accept a list of correct answers. @answerList can be an array or an actual list, e.g. strict_num_cmp_list(25,"",1,2.3,5,...). This is especially useful for instructors writing their own macros. Note that all parameters must be passed to these routines. There are no defaults. There is also a "low level" NUM_CMP_LIST ($tol,$format,$mode,$tolType,$zeroLevel,$zeroLevelTol,@answerList). Look at the file PGanswermacros.pl for details.

String compare:

  std_str_cmp( $correctAnswer ); The student's answer must match the string $correctAnswer. The match is case insensitive and multiple spaces are equivalent to 1 space. std_cs_str_cmp( $correctAnswer ); Same as std_str_cmp but case sensitive. strict_str_cmp( $correctAnswer ); The student's answer must match the string $correctAnswer exactly. unordered_str_cmp( $correctAnswer ); Usually used to match a list of unordered letters. Unordered, case insensitive, spaces ignored. unordered_cs_str_cmp( $correctAnswer ); Same as unordered_str_cmp but case sensitive. ordered_str_cmp( $correctAnswer ); Usually used to match a list of ordered letters. Ordered, case insensitive, spaces ignored. ordered_cs_str_cmp($correctAnswer ); Same as ordered_str_cmp but case sensitive.

 

std_str_cmp_list(@correctAnswerList); std_cs_str_cmp_list(@correctAnswerList); strict_str_cmp_list(@correctAnswerList); unordered_str_cmp_list(@correctAnswerList); unordered_cs_str_cmp_list(@correctAnswerList); ordered_str_cmp_list(@correctAnswerList); ordered_cs_str_cmp_list(@correctAnswerList);

These are versions which accept a list of correct answers. @correctAnswerList can be an array or an actual list, e.g. std_str_cmp_list("red", "white","blue"). This is especially useful for instructors writing their own macros. Look at the file PGanswermacros.pl for details.

 

Function compare:

  function_cmp($correctFunction) OR function_cmp($correctFunction,$var) OR function_cmp($correctFunction,$var,$llimit,$ulimit) OR function_cmp($correctFunction,$var,$llimit,$ulimit,$relpercentTol) OR function_cmp($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints) function_cmp($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints,$zeroLevel) function_cmp($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints,$zeroLevel,$zeroLevelTol)

$correctFunction must be a string, e.g. "sin(x+pi/2)". $var is also a string, e.g. "x". If not explicitly given, the various parameters have defaults which are defined in the Global.pm file or the individual course webworkCourse.ph file. The $correctFunction must be defined on the interval [$llimit,$ulimit). Typically $var defaults to "x", $llimit defaults to .00000001, $ulimit defaults to 1, $relpercentTol defaults to .1, $numOfPoints defaults to 3, $zeroLevel defaults to 1E-14, and $zeroLevelTol defaults to 1E-12. For example, if your function is sqrt(-1-x), you would have to enter something like: function_cmp("sqrt(-1-x)","x",-2,-1)
The student's answer (a function) is evaluated at $numOfPoints random points in the half open interval [$llimit,$ulimit). If the result is within $relpercentTol*$correctFunction (with values of absolute value less than $zeroLevel handled the same way as in std_num_cmp above) of $correctFunction evaluated at the same points, the student's answer is correct. Allowed functions are listed in "acceptable math functions". Syntax, arithmetic, and other errors are reported to the student.

 

Function compare up to constant (e.g. to for antidervatives):

  function_cmp_up_to_constant($correctFunction) OR function_cmp_up_to_constant($correctFunction,$var) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit,$relpercentTol) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints,$maxConstantOfIntegration) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints,$maxConstantOfIntegration,$zeroLevel) OR function_cmp_up_to_constant($correctFunction,$var,$llimit,$ulimit,$relpercentTol,$numOfPoints,$maxConstantOfIntegration,$zeroLevel,$zeroLevelTol)

$correctFunction must be a string, e.g. "sin(x) + .5*x^2". $var is also a string, e.g. "x". If not explicitly given, the various parameters have defaults which are defined in the Global.pm file or the individual course webworkCourse.ph file. Typically $var defaults to "x", $llimit defaults to .00000001, $ulimit defaults to 1, $relpercentTol defaults to .1, $numOfPoints defaults to 3, $maxConstantOfIntegration defaults to 1E8, $zeroLevel defaults to 1E-14, and $zeroLevelTol defaults to 1E-12.

Similar to function_cmp, except the student's answer only has to agree with the $correctFunction upto an additive constant. This is designed to be used when asking questions on antiderivatives. For technical reasons concerning floating point arithmetic, if the additive constant, i.e. the constant of integration, is greater (in absolute value) than $maxConstantOfIntegration AND is greater than $maxConstantOfIntegration times the correct value, WeBWorK will given an error message saying that it can not handle such a large constant of integration. This is to prevent e.g. cos(x) + 1E20 or even 1E20 as being accepted as a correct antiderivatives of sin(x) since floating point arithmetic can not tell the difference between cos(x) + 1E20, 1E20, and -cos(x) + 1E20.

 

function_cmp_abs($correctFunction,$var,$llimit,$ulimit,$absTol,$numOfPoints) function_cmp_up_to_constant_abs($correctFunction,$var,$llimit,$ulimit,$absTol,$numOfPoints,,$maxConstantOfIntegration)

These are the same as the above except that the student's answer must be within $absTol of $correctAnswer. If not explicitly given, the various parameters have the same defaults as in function_cmp and function_cmp_up_to_constant.

 

 

Details on writing your own Answer Evaluating Functions

Here is an example:


$testAnswer = sub {
my $in = shift @_; # get the answer from the student
my $correctQ; # variable will be set to 1 if the answer is
# correct.
my $PGanswerMessage ="" # message to be printed on screen
if ($in eq "Mozart") {
$correctQ =1;
}
else {
$correctQ = 0;
}
($correctQ, "Mozart" $in, $PGanswerMessage);
};
ANS( $testAnswer );



If the student's answer is "Mozart", then it will be marked right. If the "Show Answer" mode is set, then the correect answer "Mozart" will also appear, regardless of the student's answer. The student's submitted answer will be printed and finally there will be no PGanswerMessage since an empty message is returned.

Notice that we put $testAnswer into the ANS queue, not &testAnswer. This is because $testAnswer contains a reference (or pointer) to the subroutine which evaluates the answer. You can also think of the entire text of the subroutine as residing in $testAnswer, ready to spring to life and evaluate the student's answer when called upon.

Of course if the student types "Wolfgang Amadeus Mozart" their answer will be marked incorrect. However we can modify the answer evaluation subroutine above to handle this case, using Perl's pattern matching routines.

 


$testAnswer = sub {
my $in = @_; # get the answer from the student
my $correctQ; # variable will be set to 1 if the answer is
# correct.
my $PGanswerMessage ="" # message to be printed on screen
if ($in =~ /Mozart/) {
# if the string "Mozart" appears in the answer
$correctQ =1;
}
else {
$correctQ = 0;
}
($correctQ, "Wolfgang Amadeus Mozart", $in, $PGanswerMessage);
};
ANS($testAnswer);



Now the student's answer will be marked correct for either "Mozart" or for "Amadeus Mozart" or for "Mozart, Wolfgang A.". When asked to show the correct answer, however "Wolfgang Amadeus Mozart" will be printed.

The full power of perl (Program Extraction and Report Language) can be used to massage the student's answers and compare them to the correct one.

 

More examples of evaluation functions

Here are two of the standard comparison answer evaluation functions which can be found in the PGanswermacros.pl file. Look at that file for other examples.

 

To compare numerical answers use

ANS( std_num_cmp(3.456234567) );

 

Here is the actual code.

 



my $numRelPercentTolDefault = getNumRelPercentTolDefault();
my $numZeroLevelDefault = getNumZeroLevelDefault();
my $numZeroLevelTolDefault = getNumZeroLevelTolDefault();
my $numFormatDefault = getNumFormatDefault();



sub std_num_cmp { # compare numbers allowing use of elementary functions
my ($correctAnswer,$relpercentTol,$format,$zeroLevel,$zeroLevelTol) = @_;



$relpercentTol = $numRelPercentTolDefault unless defined $relpercentTol;
my $tol = .01*$relpercentTol;
$format = $numFormatDefault unless defined $format;
$zeroLevel = $numZeroLevelDefault unless defined $zeroLevel;
$zeroLevelTol = $numZeroLevelTolDefault unless defined $zeroLevelTol;
NUM_CMP($correctAnswer,$tol,$format,'std','rel',$zeroLevel,$zeroLevelTol);
}




sub NUM_CMP { # low level numeric compare
my ($correctAnswer,$tol,$format,$mode,$tolType,$zeroLevel,$zeroLevelTol) = @_;
my $formattedCorrectAnswer = prfmt($correctAnswer,$format );
my $answer_evaluator = sub {
my $in = shift @_;
my $PGanswerMessage = '';
my ($inVal,$correctVal);
$inVal = '';
$correctAnswer = &math_constants($correctAnswer);
my $formattedSubmittedAnswer = '';
$@='';
if ($correctAnswer =~ /S/) {$correctVal = eval($correctAnswer);} else { $@ = ' ';}
if ($@ or not is_a_number($correctVal)) { ##error message from eval or above
$formattedSubmittedAnswer = $@;
$formattedSubmittedAnswer =clean_up_error_msg($formattedSubmittedAnswer);
$PGanswerMessage = 'Tell your professor that there is an error in this problem';
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
}
$in = &math_constants($in);

MODE_CASE: { ## bare block for "case" statement
if ($mode eq 'std') {
last MODE_CASE;
}
if ($mode eq 'strict') {
unless (is_a_number($in)) {
$PGanswerMessage = 'You must enter a number, e.g. -6, 5.3, or 6.12E-3';
$formattedSubmittedAnswer = 'Incorrect number format';
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
}
last MODE_CASE;
}
if ($mode eq 'arith') {
unless (is_an_arithmetic_expression($in)) {
$PGanswerMessage = 'You must enter an arithmetic expression, e.g. -6 or (2.3*4+5/3)^2';
$formattedSubmittedAnswer = 'Not an arithmetic expression';
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
}
last MODE_CASE;
}
if ($mode eq 'frac') {
unless (is_a_fraction($in)) {
$PGanswerMessage = 'You must enter a number or fraction , e.g. -6 or 7/13';
$formattedSubmittedAnswer = 'Not a number or fraction';
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
}
last MODE_CASE;
}
$PGanswerMessage = 'Tell your professor that there is an error in his or her answer mechanism';
$formattedSubmittedAnswer = $in;
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
} # end of MODE_CASES bare block

$@='';
if ($in =~ /S/) {$inVal = eval($in);} else { $@ = ' ';}
if ($@) { ##error message from eval or above
$formattedSubmittedAnswer = $@;
$formattedSubmittedAnswer =clean_up_error_msg($formattedSubmittedAnswer);
$PGanswerMessage = 'There is a syntax error in your answer';
return (0,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
}
else {$formattedSubmittedAnswer = prfmt($inVal,$format);}

unless ($tolType eq 'abs') {
if ( abs($correctVal) <= $zeroLevel) {$tol = $zeroLevelTol;} ## want $tol to be non zero
else {$tol = abs($tol*$correctVal);}
}
my $correctQ =0;
my $is_a_number = is_a_number($inVal);
$correctQ = 1 if (($is_a_number) and
(abs( $inVal - $correctVal ) <= $tol));
if ($@) {$PGanswerMessage = 'There is a syntax error in your answer';}
elsif (not $is_a_number){$PGanswerMessage = 'Your answer does not evaluate to a number';}
($correctQ,$formattedCorrectAnswer,$formattedSubmittedAnswer,$PGanswerMessage);
};
$answer_evaluator;
}





Now

ANS( std_num_cmp( 2 ) );

will mark as correct 2, 2*cos(0), 1+sin(pi/2), sqrt(4), 8^(1/3), etc.

The output of std_num_cmp is placed in the ANS queue. This output is an answer evaluation function (or subroutine) which will mark 2 and its variations correct.

NUM_CMP uses the following subroutines:

 




sub is_a_number {
my ($num) = @_;
$num =~ s/^s*//; ## remove initial spaces
$num =~ s/s*$//; ## remove trailing spaces
my $is_a_number = 0;
## the following is copied from the online perl manual
if ($num =~ /^([+-]?)(?=d|.\d)d*(.\d*)?([Ee]([+-]?d+))?$/){$is_a_number = 1;}
$is_a_number;
}

sub is_a_fraction {



sub is_an_arithmetic_expression {



sub math_constants {
my($in) = @_;
$in =~s/bpib/(4*atan2(1,1))/ge;
$in =~s/beb/(exp(1))/ge;
$in =~s/^/**/g;
$in;
}



sub clean_up_error_msg
{
my $msg = $_[0];
$msg =~ s/at.*line [d]*//g;
$msg =~ s/called//g;
$msg =~ s/&main:://g;
$msg =~ s/chunk [d]*//g;
$msg;
}



sub prfmt {
my($number,$format) = @_; # attention, the order of format and number are reversed
my $out;
if ($format) {$out = sprintf($format, $number);}
else {$out = $number;}
$out;
}





To compare string answers we could use

ANS( std_str_cmp( "Mozart" ) );

This will mark as correct "Mozart", "MOZART", "MOZART " and so forth.

 


sub std_cs_str_cmp { # compare strings case sensitive
my ($correctAnswer) = shift @_; # get the correct answer
my $normalizedCorrectAnswer = $correctAnswer;
$normalizedCorrectAnswer=~ s/s*$//; # remove trailing whitespace
$normalizedCorrectAnswer=~ s/^s*//; # remove initial spaces
$normalizedCorrectAnswer=~ s/s+/ /g; # replace spaces by single space



my $answer_evaluator = sub {
my $in = shift @_;
$in=~ s/s*$//; # remove trailing whitespace
$in=~ s/^s*//; # remove initial spaces
$in=~ s/s+/ /g; # replace spaces by single space
my $correctQ = ($in eq $normalizedCorrectAnswer) ? 1: 0;
($correctQ,$normalizedCorrectAnswer,$in,"");
};
$answer_evaluator;
}




Now

ANS( std_str_cmp( "Mozart" ) );

will mark as correct "Mozart", "MOZART", "MOZART " and so forth.

The output of std_str_cmp is placed in the ANS queue. This output is an answer evaluation function (or subroutine) which will mark "MOZART" and its variations correct.

 

 

<| Post or View Comments |>


userDavid Etlinger - Re: PG answer evaluators  blueArrow
6/9/2000; 3:18:58 PM (reads: 3496, responses: 0)
docs for std_num_str_cmp and multivar_function_cmp need to be added

<| Post or View Comments |>


userDavid Etlinger - Re: PG answer evaluators  blueArrow
6/9/2000; 3:30:09 PM (reads: 3471, responses: 0)
also, add numerical_compare_with_units

<| Post or View Comments |>


userDavid Etlinger - Re: PG answer evaluators  blueArrow
6/29/2000; 10:32:42 AM (reads: 3572, responses: 0)
Descriptions for a few missing evaluators:

ANS( multivar_function_cmp( $answer, $var_reference, options ) ); $answer = string, represents function of several variables $var_reference = number (of variables), or list reference (e.g. ["var1","var2"] ) Options: $limit_reference = reference to list of lists (e.g. [[1,2],[3,4]]) $relpercentTol = relative percent tolerance in answer $numOfPoints = number of points to sample in for each variable $zeroLevel = $zeroLevelTol =

ANS( checkbox_cmp( $answer ) ); $answer = a string containing the names of the correct boxes, e.g. "ACD". Note that this means that individual checkbox names can only be one character.

ANS( radio_cmp( $answer ) ); $answer = a string containing the name of the correct radio button, e.g. "Choice1".

ANS( std_num_str_cmp( $answer, options ) ); Options $ra_legalStrings = a reference to an array containing strings which are possible answers, e.g. ["Inf", "Minf", "NaN"] $relPercentTol = $format = $zeroLevel = $zeroLevelTol =

ANS( numerical_compare_with_units( $answer, %options ) ); $answer = a string which includes both the numerical answer and the units Options (key => value pairs) mode = format = zeroTol = zeroLevelTol = tol = relTol =

Notes:

--mc_cmp can be eliminated from PGanswermacros.pl (it's commented out near the top, but it makes it confusing to read the file).

--Answer evaluators should be consistent in using new AnswerHash()

--multivar_function_cmp already has pod documentation. Can we use that for this page, or should we possible add it for the other answer evaluators?

--are str_cmp and std_str_cmp functionally equivalent? They are using separate code, but if they are the same they should be made to use the same code.

<| Post or View Comments |>