PREP 2014 Question Authoring - Archived

Allowing a comma instead of a dot for a decimal point (and other notation variants)

Allowing a comma instead of a dot for a decimal point (and other notation variants)

by Michele Titcombe -
Number of replies: 3
Related to my forum post on customizing error messages, I would also like to know how to allow answers with notation not normally used in WeBWorK.

For example:
1. How to accept 1,2 as well as 1.2 as correct (that is, using a comma for a decimal point instead of a dot)
2. How to accept reverse-square-bracket interval notation (I don't know what to call it) where ]-3,1[ is the same interval as (-3,1). Another example: ]4,5] is the same interval as (4,5].


In reply to Michele Titcombe

Re: Allowing a comma instead of a dot for a decimal point (and other notation variants)

by Paul Pearson -
Hi Michele,

As someone with a few years of experience of asking for help on online forums (and has thus learned from experience what not to do), I want to encourage everyone to have good "nettiquite", such as asking only one question per forum post.  Having one question per post avoids answers to multiple questions from becoming conflated (especially when there is a chain of multiple responses).  I know it seems like posting multiple questions in the same post "saves space" or "reduces email" (or whatever), but it actually does not work well in practice.

It is possible to make webwork interpret commas and periods as the decimal point.  I took an example from

http://webwork.maa.org/wiki/Modifying_Contexts_(advanced)

where the goal was to interpret numbers such as 1,500,000.09 as 1500000.09 and modified it so that commas get replaced by periods before the student answer gets checked.  The code is pretty advanced and messy, but you should be able to see that the important block of code is between two rather large "begin code" and "end code" delimeters, so that you can just copy and paste it.  I'm sure that Davide could improve upon this example by, for instance, creating a custom context.

Best regards,

Paul Pearson


#################################

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
);
TEXT(beginproblem());

Context("Numeric");

# ran this to figure out what the default pattern was for number and signedNumber
# warn Context()->{pattern}{number};
# warn Context()->{pattern}{signedNumber};

##################
#  Begin code that interprets both commas and periods as decimal points

# Modified the section "Here is an example that lets you use commas in your numbers:" from
# http://webwork.maa.org/wiki/Modifying_Contexts_(advanced)

   # Context()->{pattern}{number} = '(:?(:?\d{1,3}(:?\,\d{3})+|\d+)(?:\.\d*)?|\.\d+)(?:E[-+]?\d+)?';
   # Context()->{pattern}{signedNumber} = '[-+]?(:?(:?\d{1,3}(:?\,\d{3})+|\d+)(?:\.\d*)?|\.\d+)(?:E[-+]?\d+)?';

   Context()->{pattern}{number} = '(:?(:?\d{1,3}(:?\,\d{3})+|\d+)(?:[.,]\d*)?|[.,]\d+)(?:E[-+]?\d+)?';  
   Context()->{pattern}{signedNumber} = '[-+]?(?:\d+(?:[.,]\d*)?|[.,]\d+)(?:E[-+]?\d+)?';

   Context()->flags->set(NumberCheck => sub {
     my $self = shift;                              # the Number object
     my $value = $self->{value_string};             # the original string

     # $value =~ s/,//g;                              # remove commas
     $value =~ s/,/./g;                              # replace commas by periods 

     $self->{value} = $value + 0;                   # make sure it is converted to a number
     $self->{isOne} = ($self->{value} == 1);        # set marker indicating if the value is 1
     $self->{isZero} = ($self->{value} == 0);       # set marker indicating if the value is 0
   });
   Context()->update;

#  End code that interprets both commas and periods as decimal points
####################


$answer = Compute("3.14");

# in case you're interested what number and signedNumber look like after they've been changed
# warn Context()->{pattern}{number};
# warn Context()->{pattern}{signedNumber};


##############################################################
#
# Text
Context()->texStrings;
BEGIN_TEXT
Enter \( 3.14 \) or \( 3,14 \): \{ ans_rule(10) \}
END_TEXT
Context()->normalStrings;

##############################################################
# Answers
$showPartialCorrectAnswers = 1;
ANS( $answer->cmp() );

ENDDOCUMENT();
In reply to Paul Pearson

Re: Allowing a comma instead of a dot for a decimal point (and other notation variants)

by Davide Cervone -
Paul, this looks good, except for two details. The first is that the pattern for number is not right. You have left too much of the one from the Wiki, so it allows commas every three characters. You want
    Context()->{pattern}{number} = '(?:\d+(?:[.,]\d*)?|[.,]\d+)(?:E[-+]?\d+)?';
Note that this does allow ,123 as a means of entering 0.123, which looks strange to my eye. I don't know if that is the usual notation or not. If you want to force a zero before the comma, use
    Context()->{pattern}{number} = '\d+(?:[.,]\d*)?(?:E[-+]?\d+)?';
    Context()->{pattern}{signedNumber} = '[-+]\d+(?:[.,]\d*)?(?:E[-+]?\d+)?';

The second issue has to do with the text of the problem, not the answer checking. In TeX, the comma is formatted with a little space after it (it has the TeX class of punctuation, and the extra space makes things like vectors format better). When used as a decimal indicator, it should not have that space. To avoid that, use braces around the comma. So the statement of the problem should be

    BEGIN_TEXT
    Enter \( 3.14 \) or \( 3{,}14 \): \{ ans_rule(10) \}
    END_TEXT
This is a TeX subtlety that is easily missed, but if you look at the spacing for these, you will see a difference.
In reply to Michele Titcombe

Re: Allowing a comma instead of a dot for a decimal point (and other notation variants)

by Davide Cervone -
I have provided a solution to your question 2 in my answer to your other post.