WeBWorK Main Forum

Understanding quotes and decimal approximations

Re: Understanding quotes and decimal approximations

by Thomas Hoft -
Number of replies: 3

Alex (or anyone else!), 

You point out that fractional or decimal depends on how it's used, and function calls may cause decimals instead of fractions -- is there a general rule for when it stays fractional and when it's converted to decimal? 

Here's a simplified version of the issue I'm having: 

How can I code something like

$num = Compute("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;

to generate a "Correct Answer" that typesets as

42/19 cos(sqrt(3)x) 

instead of 

4.66667*cos(1.73205*x)

Doing Compute("$num_quote $func_sub->{string}") does maintain the sqrt(3) but I can't figure out anything that maintains the 42/19. 

Same question for 

Context()->variables->add(k=>"Real");
$const = Compute("31/2");
$func_const = Compute("k*sin(sqrt7x)");
$func_subbed = $func_const->substitute(k=>$const);

Hopefully that illuminates the inner workings for me, and helps me get a handle on both answer display and the weird numerical tolerance issue I described above.

Thanks! - Thomas

In reply to Thomas Hoft

Re: Understanding quotes and decimal approximations

by Alex Jordan -
Sorry for not keeping up with your previous posts. I was traveling last week and forgot about this.

$num = Compute("42/9");

Paraphrasing from Davide Cervone about this: Compute() calls Function() on the string "42/9", after first setting the context flags reduceConstants, reduceConstantFunctions, and showExtraParens to 0. Then if the formula is constant (which it is in this case), the formula is evaluated to get a Real, which is already something with a floating point value. Then Formula() is once again called on the original string "42/9" (this time with the reductions turned off), and this is used to produce the string and TeX versions for the correct answer.

So $num is a Real. Its value method gives 4.666... Its string and TeX methods give 4.66667. And its correct_ans and correct_ans_latex_string properties (properties, not methods) are respectively '42/9' and '\frac{42}{9}'.

So the things you want (those fractions in the last two properties I mentioned) are just not what you get when you use $num as a string. Instead you get the result of the string method: 4.66667.

What you really want is either:

A. Explicitly make $num be a Formula() object, and use the context flag reduceConstants => 0. So:
Context()->flags->set(reduceConstants => 0);
$num = Formula("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;

B. Use the Fraction context, which under default settings is also going to reduce your "42/9" to "14/3":
loadMacros("contextFraction.pl");
Context("Fraction");
$num = Compute("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;

However, both of these ways of doing it cause your "sqrt3" to be a decimal. This is because $func is the result of a Formula() times a Formula(), or a Fraction() times a Formula(). The result is a Formula() that did not get the special treatment that Compute() uses for setting those special string properties. So now what you probably want is to stop things like "sqrt(3)" from being executed. That's a function applied to a constant, and for that there is the flag with the slightly confusing name reduceConstantFunctions:

Context()->flags->set(reduceConstants => 0, reduceConstantFunctions => 0);
$num = Formula("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;

loadMacros("contextFraction.pl");
Context("Fraction")->flags->set(reduceConstantFunctions => 0);
$num = Compute("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;
In reply to Alex Jordan

Re: Understanding quotes and decimal approximations

by Thomas Hoft -
Alex, 

No worries, and thank you

What you describe is the inner workings that I had (have?) no clue about. I'll think about whether I want to use Formula or the Fraction Context. Meantime this works. MWE below and screenshot attached, for anyone who encounters this later...

I'll revisit my weird numerical issue with this addition, and report back. 

Thanks again - Thomas

DOCUMENT();      
loadMacros("PGstandard.pl", "PGML.pl", "PGcourse.pl");
Context("Numeric");
Context()->flags->set(reduceConstants => 0, reduceConstantFunctions => 0);
$num = Formula("42/9");
$func_sub = Compute("cos(sqrt3x)");
$func = $num*$func_sub;
Context()->variables->add(k=>"Real");
$const = Formula("31/2");
$func_const = Compute("k*sin(sqrt7x)");
$func_subbed = $func_const->substitute(k=>$const);
BEGIN_PGML
1. Number: [____________]{$num}
1. Function: [____________]{$func}
1. Constant: [____________]{$func_const}
1. Subbed: [____________]{$func_subbed}
END_PGML
ENDDOCUMENT();        


Attachment wwansfix.png
In reply to Alex Jordan

Re: Understanding quotes and decimal approximations

by Thomas Hoft -

Alex, 

This also fixed the numerical issue that led me down this rabbit hole!

Thanks! - Thomas

DOCUMENT();     
loadMacros("PGstandard.pl", "PGML.pl", "PGcourse.pl");
Context("Numeric");
Context()->variables->are(k1=>"Real", k2=>"Real", t=>"Real");
Context()->flags->set(reduceConstants => 0, reduceConstantFunctions => 0);
$y1 = Compute("e^(-4t)");
$y2 = Compute("e^(-2t)");
$yp = Compute("7/85 cos(t) + 6/85 sin(t)");
$y_gen = Compute("k1 $y1 + k2 $y2 + $yp");
$const_1 = Formula("2/17"); # k1
$const_2 = Formula("-1/5"); # k2
$y_spec = $y_gen->substitute(k1=>$const_1, k2=>$const_2); 
$y_spec->{test_points} = [ [1,1,0.005] ];
$y_gen->cmp(diagnostics=>1, 
checker => sub {
  my ($correct, $student, $ansHash) = @_;
  if ( ( ($student->substitute(k1=>1, k2=>0) == $y1 + $yp) || # one of terms is y1
         ($student->substitute(k1=>0, k2=>1) == $y1 + $yp) ) && 
       ( ($student->substitute(k1=>1, k2=>0) == $y2 + $yp) || # one of terms is y2
         ($student->substitute(k1=>0, k2=>1) == $y2 + $yp) ) #&& 
     ) 
  { return 1; } else { return 0; } 
}
);
BEGIN_PGML
(a) Find the general solution of the differential equation
[`\displaystyle \frac{d^2y}{dt^2} + 6 \frac{dy}{dt} + 8 y = \cos{t}. `]
[`y(t) = `] [______________________________________________________]{$y_gen}
Use "k1" and "k2" for the constants in your solution.
(b) Find the solution of the initial-value problem 
[`\displaystyle \frac{d^2y}{dt^2} + 6 \frac{dy}{dt} + 8 y = \cos{t}, \quad y(0)=y'(0)=0. `]
[`y(t) = `] [_______________________________________________________]{$y_spec}
END_PGML ENDDOCUMENT();        


Attachment wwDE.png