WeBWorK Problems

Allow commas in answers that are large numbers

Allow commas in answers that are large numbers

by Adam Weyhaupt -
Number of replies: 4
Hello all -

We are writing some questions for a "Mathematics for Elementary Teachers" class, and we would like to write a problem that would accept either of the following answers as correct:

8675.309
8,675.309

The context we are using is LimitedNumeric. My initial thought is to preprocess the student's answer to strip out the comma, but that seems like a bad hack. It also would allow answers like 86,75.309, which is not ideal (although we could settle for this).

Is there already a context that allows this? Is this possible?

Thanks!

Adam
In reply to Adam Weyhaupt

Re: Allow commas in answers that are large numbers

by Adam Weyhaupt -
I have a partial solution but am still having some problems. The following code does what I wanted:

Context("Currency");
Context()->currency->removeSymbol('$');

Now I'd like to write a problem that allows commas but does NOT allow the student to enter a decimal. My first attempt was to put

Parser::Number::NoDecimals(Context());

in the file, but that doesn't work. When a student enters 8,675 as the answer, Webwork complains that "decimals are not allowed".

I think that the code causing the problem is located in Parser::Number, where the lines

sub NoDecimals {
my $context = shift || Value->context;
$context->flags->set(NumberCheck=>\&_NoDecimals);
}

sub _NoDecimals {
my $self = shift;
$self->Error("You are not allowed to type decimal numbers in this problem")
unless $self->{value_string} =~ m/^[-+]?[0-9]+$/;
}

occur. That last one should also allow a comma to be present.

I tried making that change by writing my own NoDecimals function, but that doesn't work. If I change the last line to

unless $self->{value_string} =~ m/^[-+]?[0-9]+,$/;

then I get this error:

Error messages

You are not allowed to type decimal numbers in this problem; see position 2 of formula at line 21 of [TMPL]/macros/contextIntegerDEV.pl Died within main::_NoDecimals called at line 556 of [PG]/lib/Parser.pm from within Parser::Num called at line 142 of [PG]/lib/Parser.pm from within Parser::parse called at line 50 of [PG]/lib/Parser.pm from within Parser::new called at line 19 of [PG]/lib/Value/Formula.pm from within Value::Formula::new called at line 64 of [PG]/macros/Parser.pl from within main::Formula called at line 93 of [PG]/macros/Parser.pl from within main::Compute called at line 63 of [TMPL]/setCQ1practice/testmsg.pg


(contextIntegerDEV is where I put the function).

I'm stuck; thanks for any help you can provide!

Adam
In reply to Adam Weyhaupt

Re: Allow commas in answers that are large numbers

by D. Brian Walton -
The issue has to do with regular expression matching.  Here is what the original comparison is doing:

unless $self->{value_string} =~ m/^[-+]?[0-9]+$/;

*  The caret ^ says to look for a match that starts at the very beginning.
*  The brackets form a set of possible matching characters.  In this case, we allow the first character to be either - or +.  Whatever characters are inside the brackets are considered valid matches.
*  The question mark means that the first character is optional.
*  The next brackets indicate that the next character can match any of the digits 0-9.
*  The plus means that we require at least one match from 0-9, but it will include as many other numbers as possible.  So it will match any number of digits.
*  The dollar sign says we should now be at the end of the string.

If you want to ensure that commas can be included along with the digits, then you need to change the matching expression to:

unless $self->{value_string} =~ m/^[-+]?[0-9,]+$/;

However, this would allow ",,," or "0,2,55,9" as valid matches.  I do not know if you are checking the pattern of digits and commas separately somewhere else.  If you want to insist that the FIRST character is a digit, you could use:

unless $self->{value_string} =~ m/^[-+]?[0-9][0-9,]*$/;

The first bracket [0-9] requires an actual digit, while the second allows multiple matches (including 0 matches).  The difference between + and * is that + requires at least one match but as many as possible, while * allows 0 or multiple matches.

Sorry if this doesn't ultimately solve your problem, but it should at least help clarify what is happening.

Brian Walton

In reply to Adam Weyhaupt

Re: Allow commas in answers that are large numbers

by Arnold Pizer -
Hi Adam,,

Try the following script:

#!/usr/bin/env perl

my $input = shift @ARGV;

check_comma($input);


sub check_comma {
my $number = $_[0];
if (($number =~ m/^[-+]?\d{1,3}(\,\d{3})*$/) or ($number =~ m/^[-+]?\d+$/)){
print "$number matches\n"}
else {
print "$number does not match\n"};
}

Running it a few times gives:

devel ~/test_perl test_comma.pl +123456789
+123456789 matches
devel ~/test_perl test_comma.pl +123,456,789
+123,456,789 matches
devel ~/test_perl test_comma.pl +123,456789
+123,456789 does not match
devel ~/test_perl test_comma.pl +123.45
+123.45 does not match


You can put the "or" statement into the regular expression but when I tried I failed to do it correctly so I put it outside.

I think this does what you want.

Brian explained most of the notation. \d{1,3} means 1-3 digits, \d{3} means 3 digits. You can find a lot of information by doing a google search for perl regular expressions.

Arnie


In reply to Arnold Pizer

Re: Allow commas in answers that are large numbers

by Adam Weyhaupt -
Arnie and Bill -

That is perfect and does exactly what I wanted -- thanks!

Adam