Forum archive 2000-2006

Thomas R. Shemanske - fcn_cmp anomaly

Thomas R. Shemanske - fcn_cmp anomaly

by Arnold Pizer -
Number of replies: 0
inactiveTopicfcn_cmp anomaly topic started 10/9/2002; 1:03:31 AM
last post 10/11/2002; 12:05:44 AM
userThomas R. Shemanske - fcn_cmp anomaly  blueArrow
10/9/2002; 1:03:31 AM (reads: 2017, responses: 9)
In a fairly straight up function comp, a student was getting his answer marked incorrect. I have posted WW's answer, together with a variant of his which is as close as I can get to WW's answer and still be marked wrong.

BTW, if I cut and paste the correct answer, I am of course correct.

So where are these answers different in substance?

Answer 1 entered:--> 10*exp(7*t)*cos(1*t)+(6.71031260969032*e-5)*exp(7*t)*sin(t) <--

Correct answer: 10*exp(7 * t) * cos(1 * t) + 6.71031260969032e-05*exp(7 * t) * sin(1 * t)

Thanks

Tom

<| Post or View Comments |>


userArnold K. Pizer - Re: fcn_cmp anomaly  blueArrow
10/9/2002; 1:29:13 AM (reads: 2249, responses: 1)
Hi Tom,

Look at (6.71031260969032*e-5)*exp(7*t) compared with 6.71031260969032e-05*exp(7 * t)

The first is of the form (Ae-5)B and the second is of the form Ae-5B.

Arnie

<| Post or View Comments |>


userThomas R. Shemanske - Re: fcn_cmp anomaly  blueArrow
10/9/2002; 1:35:57 AM (reads: 2493, responses: 0)
Yes, but the second (which looks questionable) is WW's output

The actual answer evaluator is:

ANS( fun_cmp("$c1*exp($alpha * t) * cos($beta * t) + $c2*exp($alpha * t) * sin($beta * t)",vars=>['t'] ) );

So I am presuming WW has parsed it correctly, no?

<| Post or View Comments |>


userMichael Gage - Re: fcn_cmp anomaly  blueArrow
10/9/2002; 2:05:37 AM (reads: 2224, responses: 0)
This is where the debug facilities come in handy. Try

fun_cmp("10*exp(7*t)*cos(1*t)+(6.71031260969032*e-5)*exp(7*t)*sin(t)",debug=>1)

This will give you a trace of the answer evaluation process. With some patience you can trace through the points where this function is being evaluated and compared to the student's answer. It seems most likely this is a round off error problem that can be ameliorated by the right choice of domain for evaluation and for the tolerance of evaluating the answer.

Watching the actual evaluation process will give you a lot more information.

-- Mike

<| Post or View Comments |>


userArnold K. Pizer - Re: fcn_cmp anomaly  blueArrow
10/9/2002; 3:41:35 AM (reads: 2250, responses: 0)
Hi Tom,

This looks like one of the "Gocha's" from your newbie guide and also a new Gocha.

You say that the actual answer evaluator is:

ANS( fun_cmp("$c1*exp($alpha * t) * cos($beta * t) + $c2*exp($alpha * t) * sin($beta * t)",vars=>['t'] ) );

Look at $c2*exp($alpha * t) and the corresponding(6.71031260969032*e-5)*exp(7*t) and 6.71031260969032*e-05*exp(7*t)

so I assume $c2 = 6.71031260969032*e-05.

There may be two problems here. One is analagous to writing \( 2^$n \) when you should really write \( 2^{$n} \). If $n is 12, the first gives 2^12 and the second 2^{12}. In TeX, the first is 4 and the second is a big number. If $c is a string, this would explain the problem and is consistent with what you report. The solution is to write ($c2)*exp($alpha * t) in the answer evaluator.

 

The second is the following. $c2 looks a little like a perl number in scientific notation (and not a string) which is equal to 6.71031260969032*e-05, i.e. 6.71031260969032*10**(-05). The things I do not undertand are that "05" is an octal number which doesn't make sence here and also the notation should be 2e-15, not 2*e-15. So let's assume this should be the perl number in scientific notation 2e+29. Using the above solution gives (2e+29)*exp(7*t). Now here is the second gocha. WeBWorK interprets this as (2e+29)*exp(7*t)(where e is the number 2.71...) and not (2*10**(29))*exp(7*t) which is what perl meant. I'm not sure what a general solution is. In an author's answer passed to an answer evaluator the string 2e-2 should be interpreted as 2e-2 but the number 2e-2 in scientific notation should be interpreted as 2E-2. Since in fcn_cmp this will be embedded in a large string, I do not see how to separate the cases. Maybe we should leave this as a new gocha for a while and let problem authors beware.

<| Post or View Comments |>


userArnold K. Pizer - Re: fcn_cmp anomaly  blueArrow
10/9/2002; 9:55:25 AM (reads: 2243, responses: 0)
Here is some more information on these "Gochas". I end with a question for all the Perl experts out there. Tom has sent off line the code from his problem

 

$alpha = random(1,7);
$beta = random(1,7);



$kappa1 = random(1,10);
$kappa2 = random(1,10);
$pi = acos(-1);



$c1 = $kappa1;
$c2 = $kappa2 / exp(($pi * $alpha)/(2 * $beta));



[skip stuff]



ANS( fun_cmp("($c1) * exp($alpha * t) * cos($beta * t) + ($c2)
* exp($alpha * t) * sin($beta * t)",vars=>['t'] ) );

The seed is 1562.

As an aside he also remarks "BTW the problem has been used by 800 - 1000 students; you would have thought something would have surfaced before." Some gotchas can be subtle.

Note that above he enclosed $c2 with parentheses which took care of the first gotcha but not the second.

Here is what is happening (I think). My email to Tom:

Hi Tom,

I added the lines

warn ("c2 is $c2");
$d2 = sprintf "%.15G" ,$c2;
warn ("d2 is $d2");
which for seed 1562 prints
* c2 is 6.71031260969032e-05 at (eval 56) line 32.
* d2 is 6.71031260969032E-05 at (eval 56) line 40.

so I think it's a gotcha. My guess is that for most other seeds it's not of this form. E.g. seed =12 gives

* c2 is 4.59067077420795 at (eval 56) line 38.

Here is a possible solution. Add the line

$c2 = sprintf "%.15G" ,$c2;

This gives

Correct answer: (10) * exp(7 * t) * cos(1 * t) + (6.71031260969032E-05) * exp(7 * t) * sin(1 * t)

as the correct answer. This will be handled correctly by WeBWorK.

Adding instead the line $c2 = sprintf "%.15f" ,$c2; gives Correct answer: (10) * exp(7 * t) * cos(1 * t) + (0.000067103126097) * exp(7 * t) * sin(1 * t)

Note here you would not have to put parentheses around the $c2 (i.e. it solves both gotha's) assuming we haven't run into accuracy problems.

Here is a question for Perl experts. It looks like Perl's print command is equivalent to sprintf "%.15g" . Could we make it equivalent to sprintf "%.15G " ? This would take care of the second Gotcha. sprintf "%.15f " or some variant would take care of both but would most likely lead to other problems.

Arnie

<| Post or View Comments |>


userThomas R. Shemanske - Re: fcn_cmp anomaly  blueArrow
10/10/2002; 8:15:21 AM (reads: 2224, responses: 0)
I wanted to post the end result of my discussions with Arnie and Mike.

The WeBWorK problem asked students for a function of the form $a * f(t) for some nice function f.

For a particular value of the seed, the value of $a turned out to be $a = 4*exp(-7*pi/2);

For some reason, this particular value, when evaluated by Perl, is returned in scientific notation as the string 6.71031260969032e-5, while in general, the values returned are in decimal notation (.0000671031260969032).

At any rate, both the correct answer and the student answer pass through WeBWorK's algebra parser. Unfortunately, the algebra parser recognizes lower case e as exp(1), meaning that the expression in scientific notation was interpreted by the algebra parser as 6.71031260969032e-5 = 6.71031260969032 * exp(1) - 5, not terribly desirable.

Arnie's first suggestion was to force the format of the variable via $a = sprintf "%.15G" ,$a; which returns $a = 6.71031260969032E-5. The algebra parser recognizes the upper case e as scientific notation, and all is well. But to me this seems a very unsatisfactory state of affairs. It means that in general variables with noninteger values should always be "wrapped" with the sprintf trick.

In response to my comments, Arnie made another suggestion which is far more appealing. Instead of writing $a = 4*exp(-7*pi/2); one could write $a = "4*exp(-7*pi/2)"; (notice the quotes)

This has two advantages. First, it is parsed in the same way as a student's answer, delivering the correct value for comparison and avoiding the sprintf construct. And second, an almost more importantly, it allows the displayed answer to appear to the student as 4*exp(-7*pi/2) rather than .0000671031260969032, revealing to the student a great deal more of the structure of the answer.

For further details refer to Arnie's earlier post: http://webhost.math.rochester.edu/webworkdocs/discuss/msgReader$651

Of course you have to be a little careful not to do arithmetic with your strings, but this is a minor accommodation.

Just for the record, I still would like to know how Perl decides the format in which to render or store the computed value.

Many thanks.

Tom

<| Post or View Comments |>


userArnold K. Pizer - Re: fcn_cmp anomaly  blueArrow
10/10/2002; 10:58:36 AM (reads: 2208, responses: 0)
Hi Tom,

I believe the answer your last question is that is that Perl chooses the most compact representation, e.g. using your numbers above we see why scientific notation was choosen:
6.71031260969032e-5
.0000671031260969032
More precisely I think these routines come form the local C installation. Here is a quote from perllocale.1.html

Output produced by print() is never affected by the current locale: it is independent of whether use locale or no locale is in effect, and corresponds to what you'd get from printf() in the "C" locale. The same is true for Perl's internal conversions between numeric and string formats.

and it seems that what is used is (equivalent to) printf "%.15g" Note the lower case "g". If this were an upper case "G", scientific notation is output with a capital E, i.e. 6.71031260969032E-5, and WeBWorK would always be happy.

Arnie

<| Post or View Comments |>


userMichael Gage - Re: fcn_cmp anomaly  blueArrow
10/10/2002; 2:26:39 PM (reads: 2194, responses: 0)
The conversion which interprets e as 2.718... occurs in the subroutine math_constants. The relevant code converts a professor's or students string answer using:

 

$in	=~s/\bpi\b/(4*atan2(1,1))/ge;  # interpret pit
$in =~s/\be\b/(exp(1))/ge; # interpret e
$in =~s/\^/**/g; # replace ^ by **
if($main::useBaseTenLog) { # use base 10 definition of log (if asked)
$in =~ s/\blog\b/logten/g;
}

It's a bit of a hack, but we could require that if e is immediately preceeded by 10 digits (or 14 and a decimal point, if you want to risk it) then e is converted to E instead of being converted to exp(1).

That would cover this case. Who knows what case would be next!

Can anyone see drawbacks to this approach? Any standard examples that would be converted incorrectly?

Of course if you enter "3.35e-10" meaning "3.35*10^(-10)" you will be disappointed. And rightly so.

-- Mike

<| Post or View Comments |>


userArnold K. Pizer - Re: fcn_cmp anomaly  blueArrow
10/11/2002; 12:05:44 AM (reads: 2190, responses: 0)
One problem is that sometimes this will work and sometimes it will not.

E.g.

my $c = 11/1000000000000;
print $c;
print "\n";
gives 1.1e-11

Arnie

<| Post or View Comments |>