WeBWorK Problems

Display of student input with significant figures

Display of student input with significant figures

by Steven Fiedler -
Number of replies: 5

I ported the Perl module Math::SigFigs to PG to enable for significant figures to be checked in student responses. These routines return the expected results and numerically this appears to be a viable approach. One relatively minor issue is that the $correct and $student->value variables do not appear to be strings and thus do not retain the precision that is needed for direct use. If this issue cannot be resolved, I can recode a tolerance-type functionality in the custom answer checker.

A more significant issue is that the “Entered” and “Answer Preview” values displayed in the “Results for this submission” bar are also limited in their precision. To illustrate this, the attachment contains two screenshots. The top image displays the correct WeBWorK behavior where the student has properly calculated a numerical value but did not properly assess the correct number of sig figs. The below image represents a case where the student also provided the correct number of sig figs. In such circumstances, I could envision that some students may be confused by the limited precision shown in the regions circled in red with respect their answer (also circled).

If it is possible to rectify particularly the latter point in the problem space, I would appreciate direction. For reference, below is the portion of my code containing the question text and answer checker.


$num1="5.09738";
$num2="1000.10";

BEGIN_TEXT
Calculate the below sum and express your answer using the proper number of significant figures. $BR$BR
$num1 + $num2 = \{ ans_rule(15) \}. The answer is: \{ addSF($num1,$num2) \}$BR$BR

END_TEXT

$ans=Real(-1);  #dummy variable to permit access to ANS()
ANS($ans-> cmp(
   checker => sub {
      my ($correct,$student,$ansHash) = @_;
      my $sval = $ansHash->{original_student_ans};
      $corr_string=addSF($num1,$num2);
      if(Real($corr_string)==Real($sval)){
         $nsf_val=CountSigFigs($sval);  #num sig figs in $sval
         $nsf_corr = CountSigFigs($corr_string);  #num sig figs in corr_string
         if($nsf_val==$nsf_corr){ return 1;}
         else{
           $ansHash->{ans_message}="Incorrect number of significant figures.";
           return 0.5;
         }
       }

   }#end sub{}
 ) #end cmp()
); #end ANS()

Attachment sig_figs.png
In reply to Steven Fiedler

Re: Display of student input with significant figures

by Davide Cervone -

Here is one approach to doing what you want. This uses a subclass of Real that has a post filter that checks the significant figures. This should only be used in LimitedNumeric context, since you don't want the student to be able to do computations in their answer (where you would lose the significant figures they have entered).

Context("LimitedNumeric");

package sigfig::Real;
our @ISA = ('Value::Real');

sub cmp_postprocess {
  my $self = shift;
  my $ans = shift;
  my $correct = $self->value;
  my $student = $ans->{original_student_ans};
  $ans->{correct_ans} = $correct;
  $ans->{correct_ans_latex_string} = $correct;
  $ans->{correct_ans_latex_string} =~ s/E(.*)/\times 10^{$1}/;
  $ans->{preview_latex_string} = $student;
  $ans->{preview_latex_string} =~ s/E(.*)/\times 10^{$1}/;
  $ans->{preview_text_string} = $student;
  $ans->{student_ans} = $student;
  if ($ans->{score} == 1) {
    my ($c, $s) = ($correct, $student);
    $c =~ s/[-+.]|E.*//g;
    $s =~ s/[-+.]|E.*//g;
    if ($c ne $s) {
      $ans->{ans_message} = 'Wrong number of digits' unless $ans->{isPreview};
      $ans->score(.5);  # half credit for correct answer with wrong digits.
    }
  }
  $self->SUPER::cmp_postprocess($ans);
}

package main;

sub SigFigReal {sigfig::Real->new(@_)}

$r = SigFigReal('12.0');

TEXT($r->ans_rule(5));
ANS($r->cmp);

You could make a macro file out of this if you use it a lot. The post filter adjusts the output values (preview_latex_string, etc.) for both the correct and student answers, and then compares the correct and student answers for the correct number of digits. The algorithm used here will handle exponential notation, but you can provide your own mechanism if you prefer.

The one caveat is that you need to call SigFigReal() with a string value, not a perl real, if you want to retain trailing zeros. That looks like it should fit in with your use of addSF(), which looks like it returns a string.

In reply to Davide Cervone

Re: Display of student input with significant figures

by Steven Fiedler -

I'm resurrecting this thread.  Davide's approach on this has worked quite well but I believe there is an edge case that requires some attention.  If a student answer has the same number of decimal places as the correct answer and is within the tolerance of the correct answer, then it should be credit as correct.  However, if the two values yield slightly different strings, i.e. 1005.20 and 1005.00, the algorithm will flag it as having an incorrect number of sig figs.

I attempted to call another routine within cmp_postprocess to compare the number of sig figs of both the student answer and correct answer, but it does not appear that such a routine is within the scope cmp_postprocess.  I would appreciate any thoughts on circumventing such limitations.

In reply to Steven Fiedler

Re: Display of student input with significant figures

by Zak Zarychta -

Hi there, 

can you briefly outline how you ported the Math::SigFigs CPAN module to PG? Is this an easy task?

Zak

In reply to Zak Zarychta

Re: Display of student input with significant figures

by Steven Fiedler -
This was a fairly straightforward task but it required some attention. There were two translation issues, both of which were kindly resolved on the forum: 
  * backslashes should be converted to two sequential tildes (link) even in regular expressions
  * the $1 terms needed to be replaced in the subroutines (link)

I found it helpful to first focus on the _Simplify subroutine as it possessed no dependencies, followed by CountSigFigs, and so on.  At each point, values were checked by calling the desired routine from the text block and then rendering the problem.