WeBWorK Main Forum

help with integral calculation

help with integral calculation

by Joel Trussell -
Number of replies: 4
we have a seemingly simple problem with computing an integral. The webwork pg files gives one answer but a Matlab check gives another. I'd bet the webwork code has an error that I'm missing but I need some help finding it.
Webwork gives −23442.8571428571" role="presentation">23442.8571428571
Matlab gives
>> c=-6;d=2;cc=3;liml2=-3;limu2=3;
>> ans2 = ((c^2)/(2*cc+1))*(limu2^(2*cc+1) - liml2^(2*cc+1))+ (d^2)*(limu2-liml2) +((2*d*c)/(cc + 1))*(limu2^(cc+1)-liml2^(cc+1))
ans2 = 2.2519e+04
The pg file seems simple enough

DOCUMENT(); # This should be the first executable line in the problem.

loadMacros(
#"PGbasicmacros.pl",
#"PGanswermacros.pl",
#"PGauxiliaryFunctions.pl",
"PGstandard.pl",
"MathObjects.pl",
"AnswerFormatHelp.pl",
"PGcourse.pl",
"answerHints.pl"
);

$showPartialCorrectAnswers = 1;
# seed = 2491


$c = Real(-6);
$d = Real(2);
$cc = Real(3);
$liml2 = Real(-3);
$limu2 = Real(3);


BEGIN_TEXT
$BBOLD Definite Integrals of Basic Functions $EBOLD
$PAR
Calculate the following definite integrals
$PAR
$BBOLD b) $EBOLD \( \displaystyle \int_{$liml2}^{$limu2} ($c t^{$cc} + $d)^2 \, dt\) = \{ ans_rule()\}
END_TEXT

$ans2 = "(($c^2)/(2*$cc+1))*($limu2^(2*$cc+1) - $liml2^(2*$cc+1))
+ ($d^2)*($limu2-$liml2) +
((2*$d*$c)/($cc + 1))*($limu2^($cc+1)-$liml2^($cc+1))";

ANS(num_cmp($ans2));


ENDDOCUMENT(); # This should be the last executable line in the problem.

−23442.8571428571" role="presentation">
−23442.8571428571" role="presentation">Ma
In reply to Joel Trussell

Re: help with integral calculation

by Andras Balogh -
1. Remove the double quotes from $ans2
2. Replace ^ with **

$ans2 = (($c**2)/(2*$cc+1))*($limu2**(2*$cc+1) - $liml2**(2*$cc+1))
+ ($d**2)*($limu2-$liml2) +
((2*$d*$c)/($cc + 1))*($limu2**($cc+1)-$liml2**($cc+1));
In reply to Joel Trussell

Re: help with integral calculation

by Alex Jordan -
In Perl, ^ is not the exponentiation operator. (I believe it is bitwise XOR.) Instead, ** is the exponentiation operator. It appears to me that you are passing a string to num_cmp with ^ signs in it instead of a MathObject or a string with ** in it. Since the earlier things in the problem are MathObject Reals, you could define $ans2 as:

$ans2 = (($c**2)/(2*$cc+1))*($limu2**(2*$cc+1) - $liml2**(2*$cc+1))
+ ($d**2)*($limu2-$liml2) +
((2*$d*$c)/($cc + 1))*($limu2**($cc+1)-$liml2**($cc+1));

and $ans2 should come out as a MathObject. Then the ANS line can be:

ANS($ans2->cmp());

In reply to Alex Jordan

Re: help with integral calculation

by Joel Trussell -
I thought I had tried that - maybe i didn't do both delete " and replace ^ with ** at the same time. Anyway, that works. Can you give me a reason why the previous formula fails? Very non-intuitive to me.
In reply to Joel Trussell

Re: help with integral calculation

by Danny Glin -
There are a couple things at play here relating to data types in perl.

As Alex says, the ^ operator does not perform exponentiation in perl, but it does perform exponentiation in formulas in pg. By putting the expression in quotes you are storing it as a string which is then evaluated by the answer checker as a mathematical formula, so it recognizes ^ as exponentiation.

Perhaps some simplified examples will make this clearer.

$a = 3;
$b = $a^2;
# The value of $b will be 6, since perl treats ^ as XOR.

$c = $a**2;
# The value of $c will be 9 (3 raised to the power of 2)

$d = "$a^2";
# The value of $c will be the string "3^2".

$e = "$a**2";
# The value of $c will be the string "3**2".

Things get more complicated when you then pass these variables to an answer checker. Since the values of $b and $c are numbers, WeBWorK simply checks against these numbers, so num_cmp($b) will expect 6 as a correct answer, and num_cmp($c) will expect 9 as a correct answer.

Because num_cmp invokes the WeBWorK mathematical libraries, when you pass a string to it, it evaluates it using its methods for evaluating formulas, so it will treat ^ as exponentiation. Thus num_cmp($d) and num_cmp($e) will both expect 9 as the correct answer. The difference between these and the previous is that for $b and $c all that is passed to the checker is the value, whereas in $d and $e the checker receives the whole expression.

To put it another way, num_cmp($b) is equivalent to num_cmp(6), whereas num_cmp($d) is equivalent to num_cmp("3^2").

We still haven't got to the reason that your expression is accepted, but not evaluated correctly, which has to do with raising negative numbers to even exponents.

Consider the following:
$p = -3;
$q = $p^2;
$r = $p**2;
$s = "$p^2";
$t = "$p**2";

Again, $q and $r are the result of perl calculations. $q ends up being some large number that you get when taking an XOR with a negative number. $r is the expected value of 9. $s and $t are the strings "-3^2" and "-3**2" respectively. When you pass $s or $t to num_cmp, it will evaluate either of them to -9.

In summary, if you put a calculation in quotes, then any variables will be substituted verbatim, and only calculated later, so things like this can occur. The implication is that if you put all bases in parentheses in your answer (e.g. ($c)^2, etc.), it should evaluate properly, which would be an alternative to the suggestions given by Alex and Andras.

As a further comment, if you are using MathObjects then you should follow Alex's suggestions and use the MathObjects answer checkers instead by replacing num_cmp($ans2) with $ans2->cmp().

One other benefit of MathObjects is that you can control the display of correct answers that is shown to students by using Compute on the string you would like displayed.

For example,
$a = 2;
$b = "ln($a)";
$c = Compute("ln($a)");

If you use num_cmp($b), then the correct answer column will show "0.693...", whereas if you use $c->cmp(), then the correct answer column will show "ln(2)", which is more helpful to a student.