WeBWorK Main Forum

fun_cmp with small coefficients

fun_cmp with small coefficients

by Andras Balogh -
Number of replies: 8
I am using WeBWorK 2.3.1 under fedora.

It seems to me that for coefficients of variables
there is a problem with scientific notation
when the coefficient is smaller than 10^(-4).


For example,

$coeff = 0.000017;
$ans= "$coeff x";

\( $ans \) displays $ans as 1.7e-05x
and
ANS(fun_cmp($ans));
accepts only (the incorrect) 4.6211-5x as answer.

\($coeff\) is displayed correctly though, and ANS(num_cmp($coeff))
also works correctly.

I found an old post from Arnie that suggests for me that this problem might be related to the local C installation,
but I was not able to find solution.


Andras
In reply to Andras Balogh

Re: fun_cmp with small coefficients

by Gavin LaRose -
Hi Andras,

I think the problem is with strings and numerical values in Perl, and I'm not sure I have a good solution to the problem. I think you already established what was going on, but because it's helpful for me to restate it I'll do that.

When we define $coeff = 0.0000017, $coeff becomes a Perl numerical type, and so is stored as a numerical value, viz., 1.7*10^(-5), which Perl represents as 1.7e-05. Then when we define $ans = "$coeff x", Perl obligingly converts $coeff into a text string so that it can concatenate, and therefore gives $ans = "1.7e-05 x". After that we're using WeBWorK to interpret the answer, and WeBWorK thinks e is the constant 2.71828..., so WeBWorK interprets the answer as "1.7 e - 5x" (= 4.6211 - 5x), as you said.

I should add that I'm running a version of WeBWorK slightly past 2.4.1, not 2.3.1. I'm also seeing that the answer is displayed in a leading but not necessarily clear manner: \( $ans \) displays 1.7e−05x.

So I think the problem isn't fun_cmp per se. If I force $coeff to be a string, by setting $coeff = "0.000017", the problem actually behaves "correctly". This might be one work-around depending on how one is setting the problem up.

Gavin
In reply to Gavin LaRose

Re: fun_cmp with small coefficients

by Michael Gage -
I don't have much to add to Gavin's analysis except to mention that
E-05 will be interpreted as 10^(-5) while e will be interpreted
as exp(1) and e-05 as exp(1) - 5.

If I remember correctly Perl itself will recognize either e-05 or E-05 as 10^(-5) but we override that behavior for the small e. I remember thinking at one point about how to force perl to use capital E when writing powers of 10, but apparently I didn't come up with a solution. :-)

Just out of curiosity what happens if you use:

$coeff = 1.7 E-05;


-- Mike



In reply to Michael Gage

Re: fun_cmp with small coefficients

by Andras Balogh -
Mike,

$coeff = 1.7 E-05; and $coeff = 1.7*10^(-5); and $coeff =0.000017;
are all converted into 4.6211-5x when used with $ans= "$coeff x";
Perl understands E but it does not use it.

The real problem is when $coeff is obtained from some other random numbers and then used in a function.
I cannot force $ans="0.000017x" since I don't know what $coeff is explicitly.

I can do the following ugly hack to get around the exponential notation and to evaluate the function correctly:

$coeff = 1.7 E-05; % the point is that $coeff is some small, perhaps randomly generated coefficient

$n=1; $fixcoeff=$coeff;
while($fixcoeff){ $fixcoeff=10*$fixcoeff; $n=10*$n; }

$ans = "($fixcoeff / $n) x" will now evaluates correctly as "1.7E-05 x" or "0.000017x" without perl using e=2.71.


Here is what I don't understand: Why there is no problem with big numbers?!?!?

$coeff = 1.7E+10; $ans="$coeff x"; is displayed and evaluated as 17000000000x

Can't perl convert and use $coeff = 1.7 E-05; or other similar small number with $ans="$coeff x"; (in display and evaluation) the format 0.000017x ???

Andras
In reply to Andras Balogh

Re: fun_cmp with small coefficients

by Andras Balogh -
I meant

$n=1; $fixcoeff=$coeff;
while(abs($fixcoeff)<1){ $fixcoeff=10*$fixcoeff; $n=10*$n; }

I forgot the absolute value sign and Moodle had problem with the "less than" sign.
There is always something ;-)


Andras
In reply to Andras Balogh

Re: fun_cmp with small coefficients

by Davide Cervone -
Here is what I don't understand: Why there is no problem with big numbers?!?!?
The answer is: there is a problem, but the positive and negative exponents are somewhat asymmetric. Positive exponents will go to scientific notation at an exponent of 15 while negative exponents go to scientific notation at -5. So you would have the same problem with $coeff = 1.7e15 as you do with $coeff = 1.5e-5.

When you do a variable substitution into a text string, as in $ans = "$coeff x", perl must "stringify" the value of the variable, and for a numeric value, the value is stringified into scientific notation when the exponents are as described above. (Technically, I think it is done using the "%g" printf specification, if you are familiar with that.)

There are several ways to change this. One would be to use the uc() function to turn the lower-case "e" into an upper-case one, as in $coeff = uc(1.7e-5); $ans="$coeff x" as this should make $ans equal to "1.7E-5 x".

Perhaps the easiest way, however, would be to set perl's number format specifier, which is the variable $#. Something like $#="%G" would cause perl to use the "%G" format rather than "%g" format when stringifying numbers. (The upper-case specifier uses the upper-case E form of the scientific notation.)

Mike, perhaps that should be done somewhere in PG itself in order to prevent this problem?

Davide
In reply to Davide Cervone

Re: fun_cmp with small coefficients

by Andras Balogh -
Davide,

Thanks!, This is cool!
I double checked and Just to summarize:

$coeff=uc($coeff);

completely solves the problem of the lower/upper case e !
Does not matter if it is used as number or coefficient in function.



Andras
In reply to Davide Cervone

Re: fun_cmp with small coefficients

by Michael Gage -
Thank you Davide. I thought there was a method for forcing the upper case E but I haven't had a chance to find it. I agree -- we should place this in the pg files somewhere.

At first glance it seems like we could just place
$#="%G"
in PG.pl but we'll need some time to check for unexpected consequences.

Does that sound reasonable to you?

-- Mike
In reply to Michael Gage

Re: fun_cmp with small coefficients

by Davide Cervone -
That looks like it should work, but I don't know if anything has to be done to make it play nicely with the safe compartment stuff. It might need to be done in the DOCUMENT() call when other variables are set up.

The only consequence I can forsee would be if someone was doing string comparisons for numbers in scientific notation and used the "e" notation. There are also a couple of places where the "e" notation is handled specially in PG, and they might need tweaking. But other than that, I think it should be pretty painless (famous last words).

Davide